livewire: Bootstrap DataTable not working with Livewire action

I have one part in my project which is using bootstrap data table to display receipt status. In the table, I want to enable user to click on the red cross to verify the receipt.

The table is initially working properly as show in picture 1. But when I clicked on the red cross and trigger the livewire action, it become a normal plain table after livewire refresh (picture 2).

I wonder if I missed out some settings that need to be there in order for bootstrap data table to work? Or is it a bug which caused this issue?

Simplified blade.php:

<form action="{{ route(Constant::RECEIPT_ROUTE_STORE) }}" method="POST" enctype="multipart/form-data">
            @csrf
            <div class="mt-4">
                <table id="receipt_table" class="{{ Constant::BOOTSTRAP_DATA_TABLE_STYLE }}">
                    <thead>
                        <tr class="border bg-gray-200">
                            ...
                            <th class="p-2 border">Receipt Uploaded?</th>
                            <th class="p-2 border">Verified?</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach ($purchases as $purchase)
                            <tr class="border text-center">
                                    @if (Auth::user()->has_permission(Constant::RECEIPT_ROUTE_EDIT))
                                        @if (!is_null($purchase->receipt))
                                            @if ($purchase->receipt->is_verified)
                                                <td class="p-2 border"><span class="fas fa-check-circle text-green-400"></span></td>
                                            @else
                                                <td wire:click="toggle_verification({{ $purchase->receipt->id }})" class="p-2 border cursor-pointer"><span class="fas fa-times-circle text-red-400"></span></td>
                                            @endif
                                        @else
                                            <td class="p-2 border"><span class="fas fa-times-circle text-red-400"></span></td>
                                        @endif
                                    @endif
                            </tr>
                        @endforeach
                    </tbody>
                </table>
              </div>
        </form>

Liviwire class:

class LivewireReceipt extends Component
{
    public $purchase_id = 0;
    public function render()
    {
        return view(Constant::LIVEWIRE_RECEIPT_BLADE);
    }
    public function mount($purchase_id = 0)
    {
        $this->purchase_id = $purchase_id;
    }
    public function toggle_verification($id)
    {
        Receipt::toggle_verification($id);
    }
}

Receipt class:

class Receipt extends Model
{
    public $timestamps = true;
    use HasFactory;

    protected $fillable = [
        'name',
        'url',
        'user_id',
        'purchase_id',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
    public function purchase()
    {
        return $this->belongsTo(Purchase::class);
    }

    public static function toggle_verification($id)
    {
        $receipt = Receipt::where('id', $id)->get()->first();
        if(!is_null($receipt))
        {
            $receipt->is_verified = !$receipt->is_verified;
            $receipt->update();
        }
    }
}

Picture 1 (before action): 截圖 2020-12-19 下午4 28 58

Picture 2 (after action): 截圖 2020-12-19 下午4 29 28

  • Livewire version: [2.0]
  • Laravel version: [8.0]
  • Browser: [Chrome]

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Hi, it’s 2022 and I faced the same issue too. Luckily I found a solution to this problem

The trick is by adding a key to the main table like this:

<table ... wire:key={{ uniqid() }}>
    ...
</table>

and then dispatch an event in livewire:

$this->dispatchBrowserEvent('table-updated');

finally use an event listener to re-render your table

window.addEventListener('table-updated', event => {
      $('#table_id').DataTable({});
})