Skip to content

Commit be4a382

Browse files
authored
Create model infinite scroll
1 parent 403cb06 commit be4a382

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

src/Models/Concerns/WithScroll.php

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
3+
namespace Foxws\WireUse\Models\Concerns;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Collection;
7+
use Livewire\Attributes\Computed;
8+
use Livewire\Attributes\Locked;
9+
10+
trait WithScroll
11+
{
12+
#[Locked]
13+
public Collection $models;
14+
15+
#[Locked]
16+
public int $fetchCount = 0;
17+
18+
public function bootWithScroll(): void
19+
{
20+
data_set($this, 'models', collect(), false);
21+
}
22+
23+
public function mountWithScroll(): void
24+
{
25+
if ($this->models->isEmpty()) {
26+
$this->fetch();
27+
}
28+
}
29+
30+
#[Computed(persist: true, seconds: 3600)]
31+
public function items(): Collection
32+
{
33+
return $this->models;
34+
}
35+
36+
/**
37+
* This will fetch and merge the items.
38+
*/
39+
public function fetch(): void
40+
{
41+
if (! $this->isFetchable()) {
42+
return;
43+
}
44+
45+
$items = $this->getMergeCandidates();
46+
47+
if ($items->isNotEmpty()) {
48+
$this->mergeScrollItems($items);
49+
}
50+
51+
$this->fetchCount++;
52+
}
53+
54+
/**
55+
* This will release the current items cache.
56+
*/
57+
public function refresh(): void
58+
{
59+
unset($this->items);
60+
61+
$this->dispatch('$refresh');
62+
}
63+
64+
/**
65+
* This should be called to clear the model instances.
66+
*/
67+
public function clear(): void
68+
{
69+
$this->reset('fetchCount');
70+
71+
$this->models = collect();
72+
73+
unset($this->items);
74+
}
75+
76+
public function isFetchable(): bool
77+
{
78+
return is_null($this->getFetchLimits()) || $this->fetchCount < $this->getFetchLimits();
79+
}
80+
81+
/**
82+
* This should be called to merge the model instances.
83+
*/
84+
protected function mergeScrollItems(Collection $items): void
85+
{
86+
$items = $items
87+
->take($this->getCandidatesLimit())
88+
->reject(fn ($item) => ! $item instanceof Model)
89+
->filter()
90+
->all();
91+
92+
$this->models = $this->models
93+
->merge($items)
94+
->unique($this->getItemUniqueKey());
95+
96+
$this->refresh();
97+
}
98+
99+
/**
100+
* This should return the model instances that will be merged.
101+
*/
102+
protected function getMergeCandidates(): Collection
103+
{
104+
return collect();
105+
}
106+
107+
/**
108+
* This will ensure that the items are unique, to prevent any Livewire key conflicts.
109+
*/
110+
protected function getItemUniqueKey(): ?string
111+
{
112+
return 'id';
113+
}
114+
115+
/**
116+
* This a limit that will used when fetching and merging items.
117+
*/
118+
protected function getCandidatesLimit(): int
119+
{
120+
return 16;
121+
}
122+
123+
/**
124+
* How many times it is possible to call fetch.
125+
*/
126+
protected function getFetchLimits(): ?int
127+
{
128+
return null;
129+
}
130+
}

0 commit comments

Comments
 (0)