You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular ngFor中为选中项单独添加active类的问题解决

解决Angular ngFor列表项单独添加active类的问题

问题根源

你现在用ItemSelectStatus这个全局布尔变量控制所有列表项的active类,所有项都绑定同一个变量,所以点击时所有项的状态会一起切换,这就是问题所在。

修复步骤

  1. 替换全局状态变量:删掉ItemSelectStatus,用selectedItemId存储选中项的唯一ID(你的每个菜单都有id字段,刚好用来做唯一标识)。
  2. 修改点击事件逻辑:点击时把当前项的id赋值给selectedItemId,如果点击的是已选中的项,可以清空selectedItemId实现取消选中(可选)。
  3. 模板动态判断类名:用当前项的id和selectedItemId对比,相等就加active类。
  4. 优化遍历逻辑:没必要用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 14:03:22