Implement Load More Pagination

Normal pagination provided by Laravel is works fine.

How can we implement Load More Pagination?

  1. 4 Records displays. And Load more button.
  2. On Click Load more button 4 more records append to current 4 records list and Load more button.

Are you using the latest version of Livewire: Yes

screenshots:

Hi @shahvirag

You could achieve this by having a method that changed the pagination per page number.

class Table extends Component
{
    use WithPagination;

    public $perPage = 5;

    public function loadMore()
    {
        $this->perPage = $this->perPage + 4;
    }

    public function render()
    {
        $agencies = Agency::paginate($this->perPage);

        return view('livewire.agencies', [
            'agencies' => $agencies,
        ]);
    }
}

View:

<button wire:click="loadMore()">Load more</button>

You would need to have checks in place so as to hide the button when all records have been displayed etc.

Just a note about the answer above: this will reload all your models each time you call loadMore(). It’s a quick solution that works and if you don’t have a lot of models you anticipate loading, performance shouldn’t really be an issue.

I just wanted to make this note because load more is an something that I wanted to tackle and the comment above got me to really think about the problem a little further and how it would be possible to purely load more models.

You can have a livewire component manage your models on a per-page basis and then expose a method to load more models. It could look something like this (untested code, just typing out loud, really):

Class Row
{
    public $page;
    public $perPage;

    public function mount($page, $perPage)
    {
        $this->page = $page ? $page : 1;
        $this->perPage = $perPage ? $perPage : 1;
    }

    public function render()
    {
        $rows = Model::paginate($this->perPage, null, null, $page);

        return view('row', [
            'rows' => $rows
        ]);
    }
}
Class LoadMore
{
    public $page;
    public $perPage;
    public $loadMore;

    public function mount($page, $perPage)
    {
        $this->page = $page ? $page : 1;
        $this->perPage = $perPage ? $perPage : 1;
        $this->loadMore = false; //show the button
    }

    public function loadMore()
    {
        $this->loadMore = true;
    }

    public function render()
    {
        if ($this->loadMore) {
            $rows = Model::paginate($this->perPage, null, null, $page);

            return view('row', [
                'rows' => $rows
            ]);
        } else {
            return view('button');
        }
    }
}
// table.blade.php
<div>
    <livewire:row :page="1" :perPage="5" />
</div>

// row.blade.php
<div>
    @foreach ($rows as $row)
        {{ $row->value }}
    @endforeach

    @if($rows->hasMorePages())
        <livewire:load-more :page="{{ $page++ }}" :perPage="{{ $perPage }}"/>
    @endif
</div>

// load-more.blade.php
<div>
    <button wire:click="loadMore">Load More</button>
</div>

Again, I haven’t tried the code so I’m not quite sure it works but I’m going to jump back in and give it a shot. Just wanted to give a quick shoutout to @ashleyhood for doing the inital brainwork on this and also helping me solve one of my own issues.

// edited models for a little more clarity but please name your stuff more explicitly than this

Alright, I went ahead and implemented it and it works pretty well. I did have some stuff wrong in my initial post as it was mostly pseudocode/stream of conscious but a working implementation could look like this:

class LoadMoreButton extends Component
{
    public $page;
    public $perPage;
    public $loadMore;

    public function mount($page = 1, $perPage = 1)
    {
        $this->page = $page + 1; //increment the page
        $this->perPage = $perPage;
        $this->loadMore = false; //show the button
    }

    public function loadMore()
    {
        $this->loadMore = true;
    }

    public function render()
    {
        if ($this->loadMore) {
            $rows = Model::paginate($this->perPage, ['*'], null, $this->page);

            return view('livewire.load-more', [
                'rows' => $rows
            ]);
        } else {
            return view('livewire.load-more-button');
        }
    }
}
class LoadMore extends Component
{
    public $page;
    public $perPage;

    public function mount($page, $perPage)
    {
        $this->page = $page ? $page : 1;
        $this->perPage = $perPage ? $perPage : 1;
    }

    public function render()
    {
        $rows = Model::paginate($this->perPage, ['*'], null, $this->page);

        return view('livewire.load-more', [
            'rows' => $rows,
            'page' => $this->page
        ]);
    }
}
// table.blade.php
<div>
    <livewire:load-more :page="1" :perPage="5" />
</div>

// load-more.blade.php
<div>
    @foreach ($rows as $row)
        {{ $row->name }}
    @endforeach

    @if($rows->hasMorePages())
        <livewire:load-more-button :page="$page" :perPage="$perPage" />
    @endif
</div>

// load-more-button.blade.php
<div>
    <button wire:click="loadMore" class="bg-blue-500">Load More</button>
</div>
5 Likes