livewire: When using a custom pagination view, unable to go to the previous page.
Describe the bug While using a custom pagination view, using wire:click"previousPage" doesn’t trigger an action.
To Reproduce
// Livewire/User/History.php
namespace App\Http\Livewire\User;
use Auth;
use Livewire\Component;
use Livewire\WithPagination;
class History extends Component
{
use WithPagination;
public function render()
{
$actions = Auth::user()->actions()
->orderBy('created_at', 'desc')
->paginate(2);
return view('livewire.user.history', [
'actions' => $actions,
]);
}
}
// livewire/user/history.blade.php
<div class="flex flex-col">
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200">
<table class="min-w-full">
<thead>
<tr>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Action
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
IP address
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Time
</th>
</tr>
</thead>
<tbody>
@if($actions)
@foreach($actions as $action)
<tr class="bg-white hover:bg-gray-50">
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
{{ $action->log_name }}.{{ $action->description }}
</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
{{ $action->ip_address }}
</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
{{ \Carbon\Carbon::parse( $action->created_at )->DiffForHumans() }}
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
{{ $actions->links('livewire.table-pagination') }}
</div>
</div>
</div>
// livewire/table-pagination.blade.php
@if ($paginator->hasPages())
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
<div class="hidden sm:block">
<p class="text-sm leading-5 text-gray-700">
Showing
<span class="font-medium">{{ $paginator->firstItem() }}</span>
to
<span class="font-medium">{{ $paginator->lastItem() }}</span>
of
<span class="font-medium">{{ $paginator->total() }}</span>
results
</p>
</div>
<div class="flex-1 flex justify-between sm:justify-end">
<span class="relative z-0 inline-flex shadow-sm">
@if ($paginator->onFirstPage())
<button type="button" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm leading-5 font-medium text-gray-300 transition ease-in-out duration-150 cursor-not-allowed" disabled>
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</button>
@else
<button type="button" wire:click="previousPage" rel="prev" aria-label="@lang('pagination.previous')" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm leading-5 font-medium text-gray-500 hover:text-gray-400 focus:outline-none active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
</button>
@endif
@if ($paginator->hasMorePages())
<button type="button" wire:click="nextPage" rel="next" aria-label="@lang('pagination.next')" class="-ml-px relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm leading-5 font-medium text-gray-500 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
</svg>
</button>
@else
<button type="button" class="-ml-px relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm leading-5 font-medium text-gray-200 transition ease-in-out duration-150 cursor-not-allowed" disabled>
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
</svg>
</button>
@endif
</span>
</div>
</div>
@endif
Expected behavior On clicking the element with an attribute of wire:click=“previousPage” Livewire should supply the previous page.
Screenshots n/a
Desktop (please complete the following information):
- Chrome (latest 81.0.x)
- Firefox (latest 75.0.x)
Additional context
- Using spatie’s laravel actions package for this example.
- Livewire styles are in the html head and scripts in the body (at the end) using Laravel 7 tag syntax, loaded in the parent view using blade’s push and stack.
// .../views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Shortcut icon -->
<link rel="shortcut icon" href="">
<!-- Site title and description -->
<title>{{ is_string(config('app.page.name')) ? config('app.page.name') : config('app.page.name')[0] }} | {{ config('app.shortname') }}</title>
<meta name="description" content="{{ config('app.description') }}">
<!-- Stylesheets -->
<link rel="stylesheet" href="{{ mix('css/fonts.css') }}">
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
@stack('styles')
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body class="antialiased bg-gray-100">
@yield('content')
<!-- Scripts -->
<script src="{{ mix('js/manifest.js') }}"></script>
<script src="{{ mix('js/vendor.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
@stack('scripts')
</body>
</html>
// .../views/user/history.blade.php
@extends('layouts.app')
@push('styles')
<livewire:styles>
@endpush
@section('content')
<div class="">
@include('layouts.partials._header-nav')
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
<h1 class="text-lg leading-6 font-semibold text-gray-900">
History
</h1>
</div>
</header>
<main>
<div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
<div class="grid grid-cols-4 col-gap-8 row-gap-4">
<div class="col-span-4 md:col-span-1">
@include('user.partials._account-nav')
</div>
<div class="col-span-4 md:col-span-3">
<livewire:user.history>
</div>
</div>
</div>
</main>
</div>
@endsection
@push('scripts')
<livewire:scripts>
@endpush
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 6
- Comments: 16 (3 by maintainers)
Commits related to this issue
- Fix livewire pagination issue See: https://github.com/livewire/livewire/issues/872 — committed to SCHN-Developers/laravel-nsw-components by schn-mark-plachetta 3 years ago
The problem appears to be that the “previous” button is being rendered without a
wire:clickdirective when inactive, and then with awire:clickdirective when active, as followsThe result is that Livewire updates the attributes on the button, but doesn’t add a click handler for the
wire:clickdirective. A similar problem can occur for the next page button if thewire:clickdirective is removed.This suggests two work-arounds:
wire:clickdirective to both the disabled and active versions of the button - the disable attribute will prevent the click event from triggering thewire:clickaction.idorwire:idsuch that the two versions have different ids (or add an id to just one or the other version). Then Livewire will see the buttons as different elements and completely replace one for the other, and in the process add the click handler for thewire:clickdirective.I was able to fix this issue by adding ids to all of the elements in my pagination view.
For what it’s worth. I had this issue and I also added Id’s to all items in the paginator that were repetitive, making it difficult for Livewire to diff and the problem was solved. I used a similar view as @alexjustesen and I also had to add unique id’s to this section:
https://gist.github.com/drfraker/ff28abf4a8eb5cfc0a85cd2d9da3211d
Closing this because it’s been open too long - re-submit new issue to re-raise
Perfect explanation!