Angular ngFor中为选中项单独添加active类的问题解决
解决Angular ngFor列表项单独添加active类的问题
问题根源
你现在用ItemSelectStatus这个全局布尔变量控制所有列表项的active类,所有项都绑定同一个变量,所以点击时所有项的状态会一起切换,这就是问题所在。
修复步骤
- 替换全局状态变量:删掉
ItemSelectStatus,用selectedItemId存储选中项的唯一ID(你的每个菜单都有id字段,刚好用来做唯一标识)。 - 修改点击事件逻辑:点击时把当前项的
id赋值给selectedItemId,如果点击的是已选中的项,可以清空selectedItemId实现取消选中(可选)。 - 模板动态判断类名:用当前项的
id和selectedItemId对比,相等就加active类。 - 优化遍历逻辑:没必要用
Object.entries转数组,直接遍历chickenMenuItem,模板里不用再写item[1],更直观。
修改后的代码
模板(HTML)
<div class="mb-2 item rounded bg-white border" *ngFor="let item of chickenMenuItem; let i = index" (click)="ItemSelectClick(item)" [ngClass]="{ active: selectedItemId === item.id }"> <a href="javascript:void(0)" class="cursor-pointer"> <figure> <div class="p-5"> <img [src]="item.image" class="rounded-t mx-auto mb-4" width="75" /> <figcaption> <p class="text-lg mb-3 font-semibold leading-relaxed"> {{ item.name }} </p> <div class="flex justify-between"> <span class="leading-5 font-semibold"> {{ item.calories }} Cal. </span> <span class="leading-5 font-semibold"> ${{ item.price }} </span> </div> </figcaption> </div> </figure> </a> </div>
组件(TS)
import { Component, inject, OnInit } from "@angular/core"; import { CartItemService } from "src/app/shared/services/cart-item.service"; import { ToastService } from "src/app/shared/services/helpers/toaster.service"; @Component({ selector: "wrap-menu", templateUrl: "./wrap-menu.component.html", styleUrls: ["./wrap-menu.component.scss"], }) export class wrapComponent implements OnInit { toastService = inject(ToastService); isSelected = false; selectedItem: any; showToaster: boolean = false; toasterMessage: string = ""; // 新增:存储选中项的ID selectedItemId: number | null = null; chickenMenuItem = [ { id : 1, name: "Shawarma", image: "../../../assets/images/kebab.png", calories: "34", price: "23", }, { id : 2, name: "American Roll", image: "../../../assets/images/wrap2.png", calories: "23", price: "24", }, { id : 3, name: "Mexican Kebab", image: "../../../assets/images/item.png", calories: "34", price: "75", }, { id : 5, name: "Kebab", image: "../../../assets/images/wrap1.png", calories: "53", price: "35", }, { id : 6, name: "Spicy Fries", image: "../../../assets/images/kebab.png", calories: "22", price: "23", }, { id : 7, name: "Turkish Kebab", image: "../../../assets/images/item.png", calories: "35", price: "45", }, { id : 8, name: "Chicken Noodels", image: "../../../assets/images/item.png", calories: "23", price: "45", }, { id : 9, name: "Crispy Wings", image: "../../../assets/images/kebab.png", calories: "34", price: "98", }, ]; constructor(private cartItemServices: CartItemService) {} ItemSelectClick(item: any) { this.isSelected = true; // 点击已选中的项则取消选中,否则设置为当前项的ID this.selectedItemId = this.selectedItemId === item.id ? null : item.id; this.selectedItem = item; } ngOnInit(): void {} addItem() { this.cartItemServices.addItem(this.selectedItem); this.showToast("Item Added Successfully"); } showToast(message: string): void { this.toasterMessage = message; this.showToaster = true; setTimeout(() => this.hideToaster(), 3000); } hideToaster(): void { this.showToaster = false; this.toasterMessage = ""; } // 删掉原来的keys方法,直接遍历chickenMenuItem即可 onCancel() { this.isSelected = false; this.selectedItemId = null; // 取消选中时清空ID } }
额外说明
- 用
[src]="item.image"替代插值表达式{{ item.image }},是Angular更推荐的属性绑定方式,性能更好且避免潜在的XSS风险。 - 如果需要支持多选,就把
selectedItemId改成数组,点击时添加/移除id,模板里判断当前id是否在数组中即可。
内容的提问来源于stack exchange,提问作者Shahil Mohammed
相关产品推荐
相关产品推荐

