I am building a base layout for listing the records using Laravel Livewire.
<div class="card shadow" x-data="{ table:@entangle('table').live }">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<div class="m-0 font-weight-bold text-primary">Details</div>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
<template x-for="column in table.columns">
<div class="dropdown-item form-group">
<div class="custom-control custom-checkbox" x-id="['checkbox']">
<input :id="$id('checkbox')" class="custom-control-input" type="checkbox" x-model="table.columns.find(x => x.label === column.label).visible">
<label class="custom-control-label" :for="$id('checkbox')" x-text="column.label"></label>
</div>
</div>
</template>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
@foreach ($table->columns as $column)
<th x-show="table.columns.find(x => x.label == `{{ $column['label'] }}`).visible" data-orderable="true">{{ $column['label'] }}</th>
@endforeach
</tr>
</thead>
<tbody>
@forelse ($data as $collection)
<tr>
@foreach ($table->columns as $row)
<td class="align-middle" x-show="table.columns.find(x => x.label == `{{ $row['label'] }}`).visible">
@if (is_array($row['options']))
@isset($row['options']['_action'])
{{-- Blade Component: Table Action --}}
@endisset
{{-- Some code... --}}
@else
{{-- Display data here.... --}}
@endif
</td>
@endforeach
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
table-action.blade.php
<div class="d-flex align-content-center flex-wrap" role="group" aria-label="Basic example">
@foreach ($row['options']['_action'] as $action)
@php
$tag = isset($action['href']) ? 'a' : 'button';
$classes = [
'm-1 btn btn-sm',
'btn-icon-split' => $action['icon'] ?? false,
'btn-primary' => $action['color'] === 'primary',
'btn-danger' => $action['color'] === 'danger',
'btn-success' => $action['color'] === 'success',
];
@endphp
@if(!isset($action['can']) || Gate::allows($action['can'], $collection))
<{{ $tag }} {{ (new \Illuminate\View\ComponentAttributeBag($action))->class($classes)->except(['can', 'color', 'icon', 'label']) }}>
@isset($action['icon'])
<span class="icon"><i class="fas fa-sm {{ $action['icon'] }}"></i></span>
@endisset
@isset($action['label'])
<span class="text">{{ $action['label'] }}</span>
@endisset
</{{ $tag }}>
@endif
@endforeach
</div>
Assuming the array for $row['options']['_action']:
$options = [
'_action' => [
[
"label" => "Edit",
"can" => "update",
"icon" => "fa-edit",
"color" => "primary",
"href" => route('example.edit', [ 'record' => '_data:id' ]),
],
[
"label" => "Delete",
"can" => "delete",
"icon" => "fa-trash",
"color" => "danger",
"type" => "button",
"wire:click" => "delete(_data:id)",
"wire:confirm" => "Are you sure you want to delete this record?"
]
],
];
Here, _data:id is equivalent to $collection->id which is handled separately on the loop statement above.
Now, when I click the action button, wire:click and wire:confirm are both not working.
Let's demonstrate my issue in the short:
Button:
<button type="button" wire:click="test()" wire:confirm="Are you sure?" x-bind:click="console.log('Button clicked!')">Button</button>
Table:
<div>
{{-- Working here. --}}
<table>
{{-- Working here. --}}
<tbody>
{{-- Working here. --}}
<tr>
{{-- Working here. --}}
<td>
{{-- Not working here... --}}
</td>
</tr>
</tbody>
</table>
</div>
Even, alpine x-bind:click="console.log('Button clicked!')" is running before the button is clicked. Also, I tried moving the Blade component to the Livewire component but my issues were not resolved.
Could anyone identify the issue I'm currently encountering?
UPDATE:
After removing id="dataTable" attribute from the table, I figured out the issue, which is Bootstrap DataTables with jQuery. It seems that DataTables only allows inline event handling via onclick attribute, which complicates integration with Livewire/Alpine Directives like wire:click and wire:confirm. I've implemented the following solution as a temporary workaround.
Instead of:
[
"wire:click" => "delete(_data:id)",
"wire:confirm" => "Are you sure?"
]
Add:
[
"onclick" => "confirm('Are you sure?') && Livewire.find('" . $this->getId() . "').delete('_data:id')",
]
However, I am looking for more options or best practices to address this issue more effectively.