//routes/web.php
Route::get('/items', function() {
return view('items');
});
//resources/views/items.blade.php
@extends('layouts.app')
@section('content')
<h1 class="text-3xl font-extrabold text-gray-900 tracking-tight">Items</h1>
<livewire:load-items perPage="10" page="1" />
@endsection
@push('scripts')
<script>
var latestComponentId = '';
var isLatestComponentLoaded = false;
Livewire.hook('component.initialized', component => {
//
if('load-more-items' == component.fingerprint.name) {
latestComponentId = component.id;
isLatestComponentLoaded = true;
}
})
window.onscroll = function(ev) {
//document.body.scrollHeight worked for me insted of document.body.offsetHeight
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight && isLatestComponentLoaded) {
isLatestComponentLoaded = false;
window.livewire.find(latestComponentId).call('loadMoreItems');
}
};
</script>
@endpush
//App\Http\Livewire\LoadItems.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Item;
class LoadItems extends Component
{
public $perPage;
public $page;
public function mount($page, $perPage)
{
$this->page = $page ?? 1;
$this->perPage = $perPage ?? 10;
}
public function render()
{
$results = Item::paginate($this->perPage, ['*'], null, $this->page);
return view('livewire.load-items', [
'results' => $results
]);
}
}
//App\Http\Livewire\LoadMoreItems.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Item;
class LoadMoreItems extends Component
{
public $page;
public $perPage;
private $loadMore = false;
protected $listeners = ['loadMoreItems'];
public function mount($page, $perPage)
{
$this->page = $page ?? 1;
$this->perPage = $perPage ?? 10;
}
public function loadMoreItems()
{
$this->loadMore = true;
$this->page += 1;
}
public function render()
{
if( $this->loadMore) {
$results = Item::paginate($this->perPage, ['*'], null, $this->page);
return view('livewire.load-items', [
'results' => $results
]);
} else {
return view('livewire.load-more-items');
}
}
}
//resources/views/livewire/load-items.blade.php
<div>
<p class="font-bold">Time is {{ time() }}</p>
<ul>
@foreach($results as $result)
<li class="mt-4 border-b-2 p-4">{{$result->id}}: {{$result->name}}</li}>
@endforeach
</ul>
@if($results->hasMorePages())
<livewire:load-more-items :page="$page" :perPage="$perPage" :key="'load-more-items-'.$page" />
@endif
</div>
//resources/views/livewire/load-more-items.blade.php
<div>
<div wire:loading.delay>
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-red-700" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
</div>