Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як повернути дані з дії Livewire прямо в JavaScript через #[Json]?

Інколи дія потрібна не для того, щоб змінити стан і перемалювати компонент, а щоб отримати дані для JavaScript: варіанти автодоповнення, точки для карти, дані для графіка. Атрибут #[Json] робить дію таким ендпойнтом.

use Livewire\Attributes\Json;

new class extends Component {
    #[Json]
    public function searchCities(string $query): array
    {
        return City::query()
            ->where('name', 'like', "{$query}%")
            ->limit(10)
            ->get(['id', 'name'])
            ->toArray();
    }
};
<div x-data="{ query: '', cities: [] }">
    <input x-model="query" x-on:input.debounce.300ms="cities = await $wire.searchCities(query)">

    <template x-for="city in cities" :key="city.id">
        <button type="button" x-text="city.name" x-on:click="$wire.cityId = city.id"></button>
    </template>
</div>

Що відрізняє #[Json]-дію:

  • повернене значення приходить у JavaScript як результат Promise від $wire.method();
  • помилки валідації не потрапляють у @error, а відхиляють Promise зі структурою { status: 422, errors: { поле: [...] } }:
try {
  const result = await $wire.save();
} catch (e) {
  if (e.status === 422) showErrors(e.errors);
}
  • компонент не перерендерюється заради результату - дані живуть в Alpine.

Навіщо це замість окремого API-маршруту:

  • не потрібні маршрут, контролер, CSRF-налаштування й автентифікація для API - дія працює в контексті компонента з його станом ($this->countryId) і поточним користувачем;
  • логіка лишається поруч із компонентом, який її використовує.

Що варто пам'ятати:

  • це публічний ендпойнт: будь-хто з доступом до сторінки може викликати метод з довільними аргументами. Обмежуйте результат (limit), перевіряйте права, не повертайте зайвих полів моделей (паролі, приховані атрибути - toArray() поважає $hidden, але явний get(['id', 'name']) надійніший);
  • частота: debounce на введенні обов'язковий, інакше кожна літера - запит;
  • паралельність: такі дії часто поєднують з #[Async], щоб вони не стояли в черзі за іншими діями компонента. Але тоді результат має зберігатися лише в JavaScript, не у властивостях;
  • для великих обсягів даних (тисячі точок) варто подумати про окремий кешований ендпойнт - відповідь дії Livewire теж містить знімок стану компонента.

Докладніше в документації: Атрибут Json

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання