I'm having trouble using Livewire in combination with AlpineJS. I have a Livewire Component in form of a table. and a dropdown with actions using AlpineJS.
So each row of data has one Alpine component.
Randomly the dropdown doesn't work or only works partially and I can't figure out why. I tried x-init on the component and it did work.
file-table.blade.php:
<div class="rounded-lg bg-white shadow">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-between">
...
</div>
<table class="mt-6 w-full whitespace-nowrap text-left">
<colgroup>
<col class="w-4/12">
<col class="w-1/12">
<col class="w-3/12">
@if(is_null(auth()->user()->tenant_id))
<col class="w-2/12">
@endif
<col class="hidden lg:w-2/12">
<col class="w-full">
</colgroup>
<thead class="border-b border-slate-300 text-sm leading-6 text-gray-900">
<tr>
<th scope="col" class="py-2 pl-0 pr-4 font-semibold">
<div class="flex justify-between">
Filename
<x-table.table-order-icon wire:click="orderBy('filename')" :is-current="$orderBy === 'filename'" :ascending="$orderAsc"/>
</div>
</th>
<th scope="col" class="py-2 pl-0 pr-4 font-semibold">
<div class="flex justify-between">
Size
<x-table.table-order-icon wire:click="orderBy('size', true)" :is-current="$orderBy === 'size'" :ascending="$orderAsc"/>
</div>
</th>
<th scope="col" class="py-2 pl-0 pr-4 font-semibold">Owner</th>
<th scope="col" class="hidden py-2 pl-0 font-semibold xl:table-cell">
<div class="xl:flex xl:justify-between">
Timestamp
<x-table.table-order-icon wire:click="orderBy('timestamp')" :is-current="$orderBy === 'timestamp'" :ascending="$orderAsc"/>
</div>
</th>
<th scope="col" class="py-2 pl-0 pr-4 font-semibold"></th>
</tr>
</thead>
<tbody class="divide-y divide-slate-300/80">
@foreach($all_files as $file)
<tr>
<td class="py-2 pl-0 pr-3 text-sm font-medium text-gray-900">...</td>
<td class="px-3 py-2 pl-0 text-sm text-gray-500">...</td>
<td class="px-3 py-2 pl-0 text-sm text-gray-500">...</td>
<td class="px-3 py-2 pl-0 text-sm text-gray-500 hidden xl:table-cell">...</td>
<td class="py-2 pl-3 pr-4 text-right text-sm font-medium sm:pr-3">
<x-table.file-table-actions :file="$file"/>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="mt-8">
{{ $all_files->links() }}
</div>
</div>
</div>
FileTable.php:
class FileTable extends Component
{
use WithPagination, WithSorting;
protected array $queryMap = [
'timestamp' => 'created_at',
'filename' => 'name',
];
protected $listeners = ['file-deleted' => '$refresh', 'file-restored' => '$refresh'];
public function paginationView(): string
{
return 'components.table.pagination-links';
}
public function render(): View
{
return view('livewire.files.file-table', [
'all_files' => File::where('name', 'like', "%$this->search%")
->withTrashed(is_null(auth()->user()->tenant_id))
->orderBy($this->orderField(), $this->orderDirection())
->paginate(10),
]);
}
}
file-table-actions.blade.php
@props(['file'])
<div x-data="{actionsOpen: false}" wire:key="{{ $file->id }}" class="relative inline-block text-left">
<div x-cloak>
<button @click="actionsOpen = !actionsOpen" type="button"
class="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white p-1 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
id="menu-button" aria-expanded="true" aria-haspopup="true">
<svg x-show="actionsOpen" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-gray-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5"/>
</svg>
<svg x-show="!actionsOpen" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-gray-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5"/>
</svg>
</button>
</div>
<div @click.away="actionsOpen = false"
x-show="actionsOpen"
id="actions_{{$file->id}}" style="display: none"
class="absolute right-0 z-10 -mt-0.5 w-36 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu"
aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="py-1" role="none">
<a href="#edit-file" data-file-id="{{ $file->id }}" class="text-gray-700 group flex items-center px-4 py-2 text-sm hover:bg-indigo-400/30" role="menuitem" tabindex="-1" id="edit-file">
...
</a>
<a href="#dupe-file" data-file-id="{{ $file->id }}" class="text-gray-700 group flex items-center px-4 py-2 text-sm hover:bg-indigo-400/30" role="menuitem" tabindex="-1" id="dupe-file">
...
</a>
</div>
@if(is_null($file->deleted_at))
<div class="py-1" role="none">
<a href="#delete-file" @click.prevent="$dispatch('file-delete', {fileId: '{{ $file->id }}'})"
class="text-gray-700 group flex items-center px-4 py-2 text-sm hover:bg-indigo-400/30"
role="menuitem" tabindex="-1" id="delete-file">
...
</a>
</div>
@else
<div class="py-1" role="none">
<a href="#restore-file" @click.prevent="$dispatch('file-restore', {fileId: '{{ $file->id }}'})"
class="text-gray-700 group flex items-center px-4 py-2 text-sm hover:bg-indigo-400/30"
role="menuitem" tabindex="-1" id="restore-file">
...
</a>
</div>
@endif
</div>
</div>
I did try adding wire:ignore but that didn't help also would interfere with the fact the dropdown does need to re-render as well since the actions are dynamic.
So I hope somebody can help me find the problem in this ^^