提问人:DamsFX 提问时间:9/29/2023 更新时间:9/29/2023 访问量:81
显示使用 AlpineJS 过滤的列表中的项目数
Display number of items in list filtered with AlpineJS
问:
我有一个可以应用于图像列表的过滤器系统。 我使用 AlpineJS 只保留过滤器处于活动状态时要显示的项目。
一切正常,但我在显示与活动过滤器对应的项目数量时遇到问题。
例如,我希望能够显示 X(过滤图像)/总数。
我尝试在 Alpine 完成修改 DOM 后使用该方法进行计算,但没有成功。$nextTick()
答:
1赞
Calvin Furano
9/29/2023
#1
您可以在您所在的州添加其他属性。这可以是“getter”属性。每次访问它时,它都会计算结果的数量。numResults
get numResults () {
return this.images.filter(i => this.is_selected(i.tags)).length
},
document.addEventListener('alpine:init', () => {
Alpine.data('filterList', () => ({
// Availables filters
filters: [
{ id: 'burger', label: 'Burgers' },
{ id: 'pizza', label: 'Pizzas' },
{ id: 'drink', label: 'Drinks' },
],
// Images set
images: [
{ src: 'https://images.unsplash.com/photo-1571091718767-18b5b1457add?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=300&h=300&q=80', tags: ['burger'] },
{ src: 'https://images.unsplash.com/photo-1544145945-f90425340c7e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8OHx8ZHJpbmt8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['drink'] },
{ src: 'https://images.unsplash.com/photo-1565364909484-74ef98a238bf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fHBpenphJTIwd2luZXxlbnwwfHwwfHx8MA%3D%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['pizza', 'drink'] },
{ src: 'https://images.unsplash.com/photo-1457460866886-40ef8d4b42a0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NDl8fGJ1cmdlcnN8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['burger', 'drink'] },
{ src: 'https://images.unsplash.com/photo-1551024709-8f23befc6f87?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTJ8fGRyaW5rfGVufDB8fDB8fHww&auto=format&fit=crop&w=300&h=300&q=60', tags: ['drink'] },
{ src: 'https://images.unsplash.com/photo-1644447381354-662bfd7c78f2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTR8fGJ1cmdlcnMlMjBkcmlua3xlbnwwfHwwfHx8MA%3D%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['burger', 'drink'] },
{ src: 'https://images.unsplash.com/photo-1544029048-b78834e2c277?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MzR8fHBpenphJTIwZHJpbmt8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['pizza', 'drink'] },
{ src: 'https://images.unsplash.com/photo-1556994302-558991b74265?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTh8fGRyaW5rfGVufDB8fDB8fHww&auto=format&fit=crop&w=300&h=300&q=60', tags: ['drink']},
{ src: 'https://images.unsplash.com/photo-1513104890138-7c749659a591?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cGl6emF8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['pizza'] },
{ src: 'https://images.unsplash.com/photo-1572802419224-296b0aeee0d9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTV8fGJ1cmdlcnN8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=300&h=300&q=60', tags: ['burger'] },
{ src: 'https://images.unsplash.com/photo-1560526860-1f0e56046c85?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MjJ8fGRyaW5rfGVufDB8fDB8fHww&auto=format&fit=crop&w=300&h=300&q=60', tags: ['drink'] },
{ src: 'https://images.unsplash.com/photo-1584365685547-9a5fb6f3a70c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NjB8fHBpenphfGVufDB8fDB8fHwy&auto=format&fit=crop&w=300&h=300&q=60', tags: ['pizza'] }
],
// active tags filters
tags: [],
get numResults () {
return this.images.filter(i => this.is_selected(i.tags)).length
},
init() {},
// add/remove tag to filters
toggle(tag) {
if (this.tags.includes(tag)) {
this.tags = this.tags.filter(x => x != tag)
}
else {
this.tags.push(tag)
}
},
// check if tag is in active tag filters
is_active(tag) {
return this.tags.includes(tag)
},
// check if image's tags are in active tag filters
is_selected(t) {
var flag = false;
if(this.tags.length == 0) {
return true;
}
for(i=0; i<t.length; i++) {
if(this.tags.includes(t[i])) {
flag = true;
}
}
return flag;
},
}))
});
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<section class="max-w-7xl p-6">
<h1 class="text-3xl md:text-6xl tracking-tight leading-none font-extrabold text-cyan-500 mb-4">Filter item list with AlpineJS</h1>
<div x-data="filterList">
<div class="py-6">
<div class="flex gap-4 my-2">
<span>Click to filter list on : </span>
<template x-for="filter in filters" :key="filter.id">
<button class="px-1 py-0 bg-stone-200 rounded"
@click="toggle(filter.id)"
:class="{'bg-cyan-500 text-white':is_active(filter.id)}"
x-text="filter.label"></button>
</template>
<div>
Results: <span x-text="numResults"></span> of <span x-text="images.length"></span>
</div>
</div>
<p class="text-xs">only images with the selected tag(s) will be displayed - hover images to see their associated tags</p>
</div>
<div class="grid grid-cols-4 gap-4">
<template x-for="(image, index) in images" :key="index">
<div x-show="is_selected(image.tags);" class="group relative aspect-1" x-transition:enter="transition ease-out duration-500" x-transition:enter-start="opacity-0 scale-10" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-500" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-10">
<img :src="image.src" class="object-cover" />
<div x-text="image.tags.join(', ')" class="absolute top-[75%] left-0 right-0 bg-black/75 text-white px-1 translate-y-8 opacity-0 transition-all group-hover:translate-y-0 group-hover:opacity-100"></div>
</div>
</template>
</div>
</div>
</section>
评论