Директива wire:for⚓︎
Директива wire:for в Livewire отображает список элементов, перебирая свойство компонента — полностью на стороне клиента, без обращения к серверу.
Это аналог директивы x-for из Alpine, но она вычисляется относительно свойств вашего компонента, а не данных Alpine.
В отличие от @foreach в Blade, который формирует список на сервере, wire:for отображает его в браузере и мгновенно перерисовывает при любом изменении базового свойства — как после обновления с сервера, так и после изменения на стороне клиента, например через $wire.items.push(...).
Поскольку содержимое цикла служит шаблоном для повторяющихся элементов, wire:for необходимо использовать на теге <template>:
Сам тег <template> никогда не отображается — вместо него сразу после него для каждого элемента списка создаётся отдельный элемент.
Использование⚓︎
Ниже приведён пример отображения списка задач:
<?php
use Livewire\Component;
new class extends Component {
public $tasks = [
['id' => 1, 'title' => 'Написать документацию'],
['id' => 2, 'title' => 'Выпустить функцию'],
];
public function remove($id)
{
$this->tasks = array_values(
array_filter($this->tasks, fn ($task) => $task['id'] !== $id)
);
}
};
<div>
<ul>
<template wire:for="task in tasks" wire:for:key="task.id">
<li>
<span wire:text="task.title"></span>
<button wire:click="remove(task.id)">Удалить</button>
</li>
</template>
</ul>
</div>
Внутри цикла перебираемый элемент (в примере выше — task) доступен любой директиве Livewire или Alpine — wire:text, wire:click, x-show и так далее. Обратите внимание, что wire:click="remove(task.id)" передаёт идентификатор текущего элемента обратно в действие на сервере.
Единственный корневой элемент
Как и в случае с x-for, тег <template> должен содержать только один корневой элемент.
Ключи элементов⚓︎
Всегда указывайте ключ, чтобы список можно было эффективно переупорядочивать и обновлять без пересоздания каждого элемента. Для этого используйте wire:for:key с выражением, которое однозначно идентифицирует каждый элемент:
Синтаксис Alpine :key также поддерживается и работает точно так же:
Если ключ не указан, в качестве ключа используется индекс элемента в списке.
wire:for:key, а не wire:key
В остальных случаях в Livewire wire:key содержит статическую строку, сформированную Blade. Однако цикл шаблона требует выражение для каждого элемента, поэтому ключ задаётся через отдельный атрибут. Использование wire:key на шаблоне с wire:for приведёт к предупреждению в консоли и в остальном будет проигнорировано.
Доступ к индексу⚓︎
Как и в x-for, вместе с элементом можно получить индекс цикла:
<template wire:for="(task, index) in tasks" wire:for:key="task.id">
<li wire:text="(index + 1) + '. ' + task.title"></li>
</template>
Вложенные циклы⚓︎
Шаблоны wire:for можно вкладывать друг в друга — внутренние циклы могут обращаться к элементу внешнего цикла:
<template wire:for="column in columns" wire:for:key="column.id">
<div>
<h2 wire:text="column.title"></h2>
<template wire:for="card in column.cards" wire:for:key="card.id">
<p wire:text="card.title"></p>
</template>
</div>
</template>
wire:for и @foreach⚓︎
@foreach в Blade выполняет отображение на сервере: элементы входят в исходный HTML, а для обновления списка требуется обращение к серверу и повторная отрисовка. wire:for выполняет отображение в браузере: изменения применяются мгновенно на основе состояния на стороне клиента.
Поскольку содержимое wire:for отображается на стороне клиента, оно отсутствует в исходном HTML, сформированном сервером. Если список должен быть доступен поисковым системам или отображаться до загрузки JavaScript, используйте @foreach.
Справочник⚓︎
Поддерживаемые формы выражений:
Задайте ключ для каждого элемента с помощью wire:for:key="expression" (или Alpine :key).
У этой директивы нет модификаторов, и её необходимо использовать на теге <template>, содержащем единственный корневой элемент.