🐻
1.99
https://ux.symfony.com/foo
此组件非常标准:页面编号作为 LiveProp
,用于加载下一页的 LiveAction
,以及用于检索页面结果的 getItems
方法。
调用时,LiveAction
只需递增页码并再次渲染,显示下一页的结果。
但是...我们如何 保留
之前的结果而不是 替换
它们呢?
// ... use statements hidden - click to show
#[AsLiveComponent('ProductGrid')]
class ProductGrid
{
use ComponentToolsTrait;
use DefaultActionTrait;
private const PER_PAGE = 10;
#[LiveProp]
public int $page = 1;
public function __construct(private readonly EmojiCollection $emojis)
{
}
#[LiveAction]
public function more(): void
{
++$this->page;
}
public function hasMore(): bool
{
return \count($this->emojis) > ($this->page * self::PER_PAGE);
}
public function getItems(): array
{
$emojis = $this->emojis->paginate($this->page, self::PER_PAGE);
$colors = $this->getColors();
$items = [];
foreach ($emojis as $i => $emoji) {
$items[] = [
'id' => $id = ($this->page - 1) * self::PER_PAGE + $i,
'emoji' => $emoji,
'color' => $colors[$id % \count($colors)],
];
}
return $items;
}
public function getColors(): array
{
return [
'#fbf8cc', '#fde4cf', '#ffcfd2',
'#f1c0e8', '#cfbaf0', '#a3c4f3',
'#90dbf4', '#8eecf5', '#98f5e1',
'#b9fbc0', '#b9fbc0', '#ffc9c9',
'#d7ffc9', '#c9fffb',
];
}
}
解决方案涉及使用 data-live-ignore
属性,以及在 ProductGrid
组件中使用一些小技巧。
您只需要在 HTML 中模拟先前结果的存在。带有 data-live-ignore
属性和前一页 ID (在 🦊 下方) 的空 div
足以欺骗 LiveComponent
,使其认为先前的结果仍然存在,并且无法修改。
然后,LiveComponent
将继续添加新结果,而不是替换结果!
<div class="ProductGrid" {{ attributes }}>
<div id="results" style="display: flex; gap: 1rem; flex-direction: column;" class="p-4">
{% if page > 1 %}
{# 🦊 #}
{# Adding a fake "previous page" div is enough to trick the system #}
{# It must have the same ID than the original page #}
<div class="ProductGrid_page" id="page--{{ page - 1 }}" data-live-ignore="true"></div>
{% endif %}
{# Current page #}
<div class="ProductGrid_page" id="page--{{ page }}" data-live-ignore="true">
{% for item in this.items %}
<article class="ProductGrid_item" style="--color: {{ item.color }};">
<div class="ProductGrid_media">
<svg><use href="#svg-tshirt"/></svg>
<span>{{ item.emoji }}</span>
</div>
<data class="ProductGrid_price" value="{{ item.id }}" data-currency="$">
{{ item.id + 1 }}<small>.99</small>
</data>
</article>
{% endfor %}
</div>
<div style="display: grid; place-content: center;padding-block: 2rem;">
{% if this.hasMore %}
<button data-action="live#action" data-live-action-param="more" class="ProductGrid_more">
Load More
</button>
{% else %}
<span class="code">The End</span>
{% endif %}
</div>
</div>
</div>
作者 smnandre
发布时间 2024-06-07