Skip to content

Commit

Permalink
Create model infinite scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
francoism90 authored Oct 31, 2024
1 parent 403cb06 commit be4a382
Showing 1 changed file with 130 additions and 0 deletions.
130 changes: 130 additions & 0 deletions src/Models/Concerns/WithScroll.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace Foxws\WireUse\Models\Concerns;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;

trait WithScroll
{
#[Locked]
public Collection $models;

#[Locked]
public int $fetchCount = 0;

public function bootWithScroll(): void
{
data_set($this, 'models', collect(), false);
}

public function mountWithScroll(): void
{
if ($this->models->isEmpty()) {
$this->fetch();
}
}

#[Computed(persist: true, seconds: 3600)]
public function items(): Collection
{
return $this->models;
}

/**
* This will fetch and merge the items.
*/
public function fetch(): void
{
if (! $this->isFetchable()) {
return;
}

$items = $this->getMergeCandidates();

if ($items->isNotEmpty()) {
$this->mergeScrollItems($items);
}

$this->fetchCount++;
}

/**
* This will release the current items cache.
*/
public function refresh(): void
{
unset($this->items);

$this->dispatch('$refresh');
}

/**
* This should be called to clear the model instances.
*/
public function clear(): void
{
$this->reset('fetchCount');

$this->models = collect();

unset($this->items);
}

public function isFetchable(): bool
{
return is_null($this->getFetchLimits()) || $this->fetchCount < $this->getFetchLimits();
}

/**
* This should be called to merge the model instances.
*/
protected function mergeScrollItems(Collection $items): void
{
$items = $items
->take($this->getCandidatesLimit())
->reject(fn ($item) => ! $item instanceof Model)
->filter()
->all();

$this->models = $this->models
->merge($items)
->unique($this->getItemUniqueKey());

$this->refresh();
}

/**
* This should return the model instances that will be merged.
*/
protected function getMergeCandidates(): Collection
{
return collect();
}

/**
* This will ensure that the items are unique, to prevent any Livewire key conflicts.
*/
protected function getItemUniqueKey(): ?string
{
return 'id';
}

/**
* This a limit that will used when fetching and merging items.
*/
protected function getCandidatesLimit(): int
{
return 16;
}

/**
* How many times it is possible to call fetch.
*/
protected function getFetchLimits(): ?int
{
return null;
}
}

0 comments on commit be4a382

Please sign in to comment.