Создание пользовательских элементов blade html в blade

#laravel #laravel-blade #laravel-7

#laravel #laravel-blade #laravel-7

Вопрос:

У меня есть некоторые часто используемые сложные элементы пользовательского интерфейса, созданные с помощью HTML (такие как карточки, группы кнопок и т.д.) Для этой цели я хотел бы создать повторно используемые элементы blade.

Самое близкое решение, которое я нашел, — это пользовательские директивы blade.

Я определил простую директиву card следующим образом:

 Blade::directive('card', function ($expression) {
    list($title, $icon, $buttons) = explode(',', str_replace(["'"], '', $expression));

    $str = '<div class="card card-custom">
                         <div class="card-header">
                             <div class="card-title">
                                 <span class="card-icon">
                                     <i class="'.$icon.'"></i>
                                 </span>
                                 <h3 class="card-label">'.$title.'
                             </div>
                             <div class="card-toolbar">'.$buttons.'
                             </div>
                         </div>
                         <div class="card-body">';
    return "<?php echo '".$str."'; ? >";
});

Blade::directive('endcard', function () {
    return '</div></div>';
})
  

и в моем blade я просто называю это так:

 @card('Dashboard', 'fa fa-tachometer', $buttonsHtml)
    <div> Card content here...</div>
@endcard
  

Которые хотели бы прикрепленное изображение.

введите описание изображения здесь

Проблема в том, что я не могу передать какой-либо параметр в качестве переменной (например, $ buttonsHtml), потому что он будет восприниматься буквально как «$ buttonsHtml».

Я не видел, чтобы кто-нибудь пытался оценить переменную перед передачей ее в пользовательскую директиву. Возможно ли это вообще?

Было бы бесполезно, если бы мне нужно было передать фактическое значение переменной $ buttonsHtml, поскольку оно генерируется какой-либо другой функцией. У кого-нибудь есть идея обойти или даже заменить использование пользовательских директив?

Ответ №1:

Вы можете использовать блочные компоненты для создания повторно используемых HTML-элементов, и поскольку ваш card элемент довольно прост, я бы использовал анонимный компонент.

Создайте следующий файл:

«resources/views/components/card.blade.php «

 @props([
'title' => '',
'icon' => '',
])

<div class="card card-custom">
    <div class="card-header">
        <div class="card-title">
            <span class="card-icon"><i class="{{ $icon }}"></i></span>
            <h3 class="card-label">{{ $title }}</h3>
        </div>
        @if(isset($toolbar))
            <div class="card-toolbar">{{ $toolbar }}</div>
        @endif
    </div>
    <div class="card-body">{{ $slot }}</div>
</div>
  

Теперь вы можете использовать его таким образом в своих файлах просмотра:

 <!-- without toolbar -->
<x-card title="Dashboard" icon="fa fa-tachometer">
    <div> Card content here...</div>
</x-card>

<!-- with toolbar -->
<x-card title="Dashboard" icon="fa fa-tachometer">
    <x-slot name="toolbar">
        {!! $buttonsHtml !!}
    </x-slot>

    <div> Card content here...</div>
</x-card>
  

Комментарии:

1. Большое вам спасибо за то, что приняли его для анонимного компонента.

Ответ №2:

В Laravel 7 представлены компоненты Blade. Это позволяет вам делать именно это. Смотрите здесь:https://laravel.com/docs/7.x/blade#components.

Эти компоненты могут вызываться с использованием HTML-подобных тегов, и вы можете передавать данные.

В вашем случае это может выглядеть следующим образом:

Именно так вы бы назвали свой компонент

 <x-card title="Dashboard" icon="fa fa-tachometer">
    <x-slot name="buttons">
        Your buttons HTML here
    </x-slot>
    Card content here
</x-card>
  

resources/views/components/card.blade.php

 <div class="card card-custom">
    <div class="card-header">
        <div class="card-title">
            <span class="card-icon">
                <i class="{{ $icon }}"></i>
            </span>
            <h3 class="card-label">{{ $title }}</h3>
        </div>
        <div class="card-toolbar">
            {{ $buttons }}
        </div>
    </div>
    <div class="card-body">
        {{ $slot }}
    </div>
</div>
  

app/View/Components/Card.php

 class Card extends Component
{
    /** @var string Card title */
    public $title;

    /** @var string Card icon */
    public $icon;
    
    public function __construct($title, $icon)
    {
        $this->title = $title;
        $this->icon = $icon;
    }

    public function render()
    {
        return view('components.card');
    }
}
  

Комментарии:

1. Большое вам спасибо, это был отличный ответ. Я выбрал другой ответ только для чуть меньшего количества кода, а это именно то, что я искал.

Ответ №3:

Это, безусловно, уникальный и интересный подход. Попробуйте записать это в кавычках без знака ‘$’, например :

 `@card('Dashboard', 'fa fa-tachometer', 'buttonsHtml')
    <div> Card content here...</div>
@endcard`
  

Это может сработать

Комментарии:

1. Спасибо, я на самом деле перепробовал так много вариантов передачи переменной, но безуспешно, я думаю, мне нужен более сложный подход к оценке.