I’m building some kinds of tag selection element for my Laravel 11 Livewire v3 project. A user can select models which are saved to a database and then click to remove them. When I click to add/remove new models, my HTML badges aren’t being updated. I need realtime HTML re-rendering based on the data from the database to ensure accuracy and reliability. What am I missing?
Here’s my HTML livewire component file:
<div x-data>
<div class="cursor-pointer border border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-blue-500 dark:focus:border-blue-600 focus:ring-blue-500 dark:focus:ring-blue-600 rounded-md shadow-sm min-h-10 w-ful gap-4l" wire:click="toggleVisibility" x-on:click.away="$wire.justClose()">
@if (isset($selectedModels))
@foreach ($selectedModels as $index => $model)
<x-badge wire:click="removeModel('{{ $model['pivot']['id'] }}')" small class="bg-slate-100 text-slate-800 ml-2 z-10">
{{ $model['name'] ?? '' }}
</x-badge>
@endforeach
@endif
</div>
@if ($isOpen)
<ul class="border-b border-l border-r border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-blue-500 dark:focus:border-blue-600 focus:ring-blue-500 dark:focus:ring-blue-600 rounded-b-md shadow-sm w-full">
@foreach ($selectableModels as $model)
<li wire:click="addModel('{{ $model->id }}')" class="py-1 px-4 w-full cursor-pointer hover:bg-gray-100">
{{ $model['name'] ?? 'not set' }}
</li>
@endforeach
</ul>
@endif
</div>
And the PHP class:
<?php
namespace AppLivewireComponents;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentCollection;
use AppModelsSite;
use AppModelsSiteable;
use LivewireComponent;
class ModelAssociation extends Component
{
public Model $model;
public Collection $selectableModels;
public array $selectedModels;
public bool $isOpen = false;
public function mount()
{
$this->updateModels();
}
public function updateModels()
{
$model = $this->model->load('sites');
$exclude = $model->sites->pluck('id')->toArray();
$this->selectedModels = $model->sites->toArray();
$this->selectableModels = auth()->user()->sites()->whereNotIn('id', $exclude)->get();
}
public function toggleVisibility()
{
$this->isOpen = ! $this->isOpen;
}
public function justClose()
{
$this->isOpen = false;
}
public function addModel(string $siteId)
{
$modelClass = get_class($this->model);
$target = $modelClass::with('sites')->find($this->model->id);
Siteable::updateOrCreate([
'site_id' => $siteId,
'siteable_type' => get_class($target),
'siteable_id' => $target->id
], []);
// $this->selectedModels = collect($target?->sites ?? [])->toArray();
$this->dispatch('siteable-added');
}
public function removeModel(string $siteableId)
{
$siteable = Siteable::find($siteableId);
if ($siteable) $siteable->delete();
$this->updateModels();
}
public function render()
{
return view('livewire.components.model-association');
}
}
I’ve tried the $refresh
with events, and tried moving the part that outputs the array into a method to call when adding / removing.