Infinite Scroll
- Project
- WireUse
- Tags
- components, blade, views
- Updated
- Last updated 4 days ago
Introduction
Infinite scrolling is an approach which loads content continuously as the user scrolls down or on button click.
While many tutorials increase the query limit (->take()
), this trait focuses on fetching as paginate.
This should decrease database load, and make fetching while merging items a lot more efficient.
Usage
Tip: Optionally you may want to include
Livewire\WithoutUrlPagination
to hide?page=
args.
To use infinite scrolling, implement the WithPaginateScroll
trait on a Livewire component:
use Domain\Tags\Models\Tag;
use Foxws\WireUse\Models\Concerns\WithPaginateScroll;
use Illuminate\Pagination\Paginator;
use Livewire\Component;
class Section extends Component
{
use WithPaginateScroll;
/**
* This builds upon the WithQueryBuilder trait.
*/
protected function getBuilder(): Paginator
{
return $this->getQuery()
->where('state', 'published')
->simplePaginate(
perPage: $this->getCandidatesLimit(),
page: $this->getPage(),
);
}
/**
* Defines the model class used to call the query builder.
*/
protected function getModelClass(): ?string
{
return Tag::class;
}
/**
* This a limit that will used when fetching and merging items.
*/
protected function getCandidatesLimit(): int
{
return 12;
}
/**
* How many times it is possible to call fetch.
*/
protected function getFetchLimits(): ?int
{
return 3; // total items 12 * 3 = 36
}
}
Create a Blade view (e.g. tags.blade.php
):
<div>
<div
wire:scroll
wire:poll.900s
class="grid grid-cols-2 overflow-y-scroll"
>
@foreach ($this->items as $tag)
<div wire:key="{{ $tag->getRouteKey() }}">
<livewire:tags.item :$tag :key="$tag->getRouteKey()" />
</div>
@endforeach
</div>
<nav class="flex items-center w-full">
@if ($this->isFetchable())
<button
wire:loading.attr="disabled"
wire:click="nextPage"
>
Load more
</button>
@endif
</nav>
</div>
It is also possible to use an 'on-scroll' approach using an Alpine intersect:
<div x-data>
<div
wire:poll.900s
class="grid grid-cols-2 overflow-y-scroll"
>
@foreach ($this->items as $tag)
<div wire:key="{{ $tag->getRouteKey() }}">
<livewire:tags.item :$tag :key="$tag->getRouteKey()" />
</div>
@endforeach
</div>
<div
class="w-full h-0 min-h-0"
x-intersect.full="$wire.nextPage()"
/>
</div>