Перейти к содержанию

Директива wire:for⚓︎

Директива wire:for в Livewire отображает список элементов, перебирая свойство компонента — полностью на стороне клиента, без обращения к серверу.

Это аналог директивы x-for из Alpine, но она вычисляется относительно свойств вашего компонента, а не данных Alpine.

В отличие от @foreach в Blade, который формирует список на сервере, wire:for отображает его в браузере и мгновенно перерисовывает при любом изменении базового свойства — как после обновления с сервера, так и после изменения на стороне клиента, например через $wire.items.push(...).

Поскольку содержимое цикла служит шаблоном для повторяющихся элементов, wire:for необходимо использовать на теге <template>:

<template wire:for="item in items" wire:for:key="item.id">
    <div>...</div>
</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 с выражением, которое однозначно идентифицирует каждый элемент:

<template wire:for="task in tasks" wire:for:key="task.id">

Синтаксис Alpine :key также поддерживается и работает точно так же:

<template wire:for="task in tasks" :key="task.id">

Если ключ не указан, в качестве ключа используется индекс элемента в списке.

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.

Справочник⚓︎

<template wire:for="item in items" wire:for:key="item.id">
    <div>...</div>
</template>

Поддерживаемые формы выражений:

wire:for="item in items"
wire:for="(item, index) in items"

Задайте ключ для каждого элемента с помощью wire:for:key="expression" (или Alpine :key).

У этой директивы нет модификаторов, и её необходимо использовать на теге <template>, содержащем единственный корневой элемент.