How do i build a load more pagination using livewire

How to load more data with the click of a button when using laravel livewire for data pagination…
I don’t know how to go about this…
Any help is appreciated…

1 Like

I don’t know how efficient this is, but you can add a count property to your component and increase it by 5 or whatever when the button is clicked, and limit your query by count in the render method.

1 Like

Include use WithPagination; inside of the component class (add use Livewire/WithPagination; to the file itself if you don’t automatically pull it in your editor).

Add the paginate() method on your model you are passing into the view 'posts' => \App\Post::paginate($numPerPage) or however you pass it.

Use the default {{ $posts->links() }} laravel method, the WithPagination trait overrides it for livewire to use. If you don’t use the trait, it will still work, but you will get full page reloads on the links.

1 Like

You’ll have to post some code for us to see and work through, but in general the above comments should do it.

1 Like

Hi @moneya,

I think you can combining eloquent pagination with livewire events/listeners to solve your problem.

Let me show you an example.
Imagine you want to build a component that lists all the users in your app. It shows the first 10 records when loaded, then every time you click “load more” button, it appends 10 records to the previously loaded records, and so on…

/** app/Http/Livewire/ListUsers.php */

class ListUsers extends Component
{
    /** @var User[] */
    public array $users = [];

    protected int $count = 0;

    protected $listeners = ['loadMoreData'];

    public function render()
    {
        return view('livewire.list-users');
    }

    public function loadData(): void
    {
        $this->count++;
        
        // for more info about `paginate()` method (see the link below)
        // https://github.com/laravel/framework/blob/e93c478adc5f1524d3dc77fea53a3c4cd34fd79b/src/Illuminate/Database/Eloquent/Builder.php#L748
        array_push($this->data, ...User::paginate(10, ['*'], 'page', $page)->items());
    }

    public function loadMoreData(): void
    {
        $page = ++$this->count;
        
        array_push($this->data, ...User::paginate(10, ['*'], 'page', $page)->items);
    }
}
/** resources/views/livewire/list-users.blade.php */

<div wire:init="loadData">

  <ul>
    @foreach($users as $user)
      <li wire:key="$loop->index()">
        {{ $user->name }}
      </li>
    @endif
  </ul>
  
  <button type="button" wire:click="$emit('loadMoreData')">
    Load more
  </button>
  
</div>

…and you can write your test in this way

class ListUsersTest extends TestCase
{
    /** @test  */
    function it_lists_users()
    {
        Livewire::test(ListUsers::class)
            ->call('loadData')
            ->tap(function($test) {
            	$this->assertCount(10, $test->get('users'));
            })
            ->emit('loadMoreData')
            ->tap(function($test) {
            	$this->assertCount(20, $test->get('users'));
            })
            ->emit('loadMoreData')
            ->tap(function($test) {
            	$this->assertCount(30, $test->get('users'));
            });
    }
}

I hope this can help you!

Happy coding :wink: !

2 Likes

Great example @leMaur. Thanks for sharing.

1 Like

Awesome, Thanks for sharing

Thanks for this idea, the problem is livewire for some reason doesnt support sending models to the next request as it casts the models to array that will result in errors calling methods on array!

Do you have any idea regarding this?