# Adding Loading States to Pagination Buttons in Blade Tables

When a user clicks Prev/Next on a custom blade table, there's no visual feedback by default.
This documents the pattern used to add button loading text and table dimming.

---

## What it does

- Clicked Prev/Next button shows **"Loading…"** in place of its label
- All pager buttons are **disabled** while any page is loading
- The table dims with a **white overlay** until the new page renders

---

## The pattern

### 1. Pager buttons

Replace plain `wire:click` buttons with this structure:

```blade
<button
    class="pager-btn"
    wire:click="prevPage"
    wire:loading.attr="disabled"
    wire:target="firstPage,prevPage,nextPage,lastPage"
    @if($page <= 1) disabled @endif
>
    <span wire:loading.remove wire:target="prevPage">‹ Prev</span>
    <span wire:loading       wire:target="prevPage">Loading…</span>
</button>

<button
    class="pager-btn"
    wire:click="nextPage"
    wire:loading.attr="disabled"
    wire:target="firstPage,prevPage,nextPage,lastPage"
    @if($page >= $totalPages) disabled @endif
>
    <span wire:loading.remove wire:target="nextPage">Next ›</span>
    <span wire:loading       wire:target="nextPage">Loading…</span>
</button>
```

**Key points:**
- `wire:loading.attr="disabled"` targets ALL four pager actions — prevents double-clicks while loading
- The inner `wire:loading` / `wire:loading.remove` pair targets only its OWN action — so only the clicked button says "Loading…", not all of them
- First `«` and last `»` buttons only need `wire:loading.attr="disabled"` — no inner label swap needed as they show just an icon

### 2. Table dimming overlay

Wrap the table in a `position:relative` container and add a transparent overlay div:

```blade
<div style="overflow-x:auto; position:relative;">

    {{-- Overlay dims the table while loading --}}
    <div
        wire:loading
        wire:target="firstPage,prevPage,nextPage,lastPage,perPage"
        style="position:absolute; inset:0; background:rgba(255,255,255,.6); z-index:10; border-radius:.5rem;"
    ></div>

    <table
        class="am-tbl"
        wire:loading.class="opacity-50"
        wire:target="firstPage,prevPage,nextPage,lastPage,perPage"
    >
        ...
    </table>
</div>
```

**Key points:**
- The overlay `div` is `display:none` by default — Livewire shows it automatically during loading
- `position:absolute; inset:0` makes it cover the whole table area
- `z-index:10` ensures it sits above the table rows
- `wire:loading.class="opacity-50"` on the `<table>` adds a second dimming layer for extra effect (optional but looks good)
- Include `perPage` in the target list so the overlay also fires when the per-page select changes

---

## Per-page select

No changes needed to the select itself — just make sure `perPage` is in all `wire:target` lists above:

```blade
<select wire:model.live="perPage" ...>
    <option value="25">25 / page</option>
    <option value="50">50 / page</option>
    <option value="100">100 / page</option>
</select>
```

---

## Checklist when applying to a new table

- [ ] `wire:loading.attr="disabled"` on ALL pager buttons, targeting all page actions
- [ ] `wire:loading` / `wire:loading.remove` inner spans on Prev and Next buttons only
- [ ] Wrapper `div` has `position:relative`
- [ ] Overlay `div` with `wire:loading` and `wire:target` inside the wrapper
- [ ] `wire:loading.class="opacity-50"` on the `<table>` element
- [ ] `perPage` included in targets if there is a per-page select

---

## Files this was applied to

- `plugins/webkul/allmakes-psp/resources/views/filament/pages/allmakes-dashboard.blade.php`
