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

如何处理*ngFor渲染多列表项的独立Toggle功能

解决Angular *ngFor列表中Toggle按钮仅展开当前行的问题

嘿,我一眼就看出问题所在了——你所有的列表项都在共享同一个全局布尔变量 toggelFlagvfe!不管点击哪一行的按钮,这个变量的状态变化都会同步影响所有绑定它的元素,所以才会出现“点一个按钮全展开”的情况。

下面给你两种实用的解决方案,选哪种看你需求:

方案一:给每个数据项单独加展开状态(最简单直接)

直接在你的gDatas数组的每个对象里新增一个isExpanded属性,用来单独控制当前行的展开/收起状态:

组件类代码修改

export class VentClass {
  gDatas: any[];
  constructor() {
    // 初始化数据时给每个item加上isExpanded,默认是收起状态(false)
    this.gDatas = [
      {"ID":"85","Source":"Local","Eqpmnts":[{"ID":"10","CreatedBy":"jmzw"},{"ID":"10","CreatedBy":"jmzw"}], isExpanded: false},
      {"ID":"86","Source":"Local","Eqpmnts":[{"ID":"10","CreatedBy":"jmzw"}], isExpanded: false},
      {"ID":"87","Source":"EC","Eqpmnts":[],"isExpanded": false}
    ];
  }

  toggleSection(item) {
    // 直接切换当前item的isExpanded状态,不用再判断true/false,一行搞定
    item.isExpanded = !item.isExpanded;
  }
}

模板代码修改

把模板里所有绑定toggelFlagvfe的地方,全部换成当前item的isExpanded:

<ion-row *ngFor="let item of gDatas">
  <ion-col col-1>
    <button (click)="toggleSection(item)" detail-none 
            [ngClass]="{'section-active1': item.isExpanded, 'section1': !item.isExpanded}">
      <ion-icon item-left name="arrow-dropright" *ngIf="!item.isExpanded"></ion-icon>
      <ion-icon item-left name="arrow-dropdown" *ngIf="item.isExpanded"></ion-icon>
    </button>
  </ion-col>
  <ion-col col-2>
    <ion-input type="number" [(ngModel)]="item.ID" text-wrap></ion-input>
  </ion-col>
  <ion-col col-2>
    <ion-label>{{item.Source}} </ion-label>
  </ion-col>
  <!-- 这里改成用item.isExpanded控制详情显示 -->
  <div *ngIf="item.isExpanded">
    <ion-grid >
      <ion-row *ngFor="let eqpm of item.Eqpmnts" nowrap>
        <ion-col>
          <ion-label>{{eqpm.ID}} </ion-label>
          <ion-label>{{eqpm.CreatedBy}} </ion-label>
        </ion-col>
      </ion-row>
    </ion-grid>
  </div>
</ion-row>

方案二:用单独对象存状态(不修改原始数据)

如果不想改动你的原始gDatas数据,可以创建一个单独的对象,用每个item的ID作为键来存储对应的展开状态:

组件类代码修改

export class VentClass {
  gDatas: any[];
  // 用对象来记录每个item的展开状态,键是item的ID
  expandedStates: {[key: string]: boolean} = {};

  constructor() {
    this.gDatas = [
      {"ID":"85","Source":"Local","Eqpmnts":[{"ID":"10","CreatedBy":"jmzw"},{"ID":"10","CreatedBy":"jmzw"}]},
      {"ID":"86","Source":"Local","Eqpmnts":[{"ID":"10","CreatedBy":"jmzw"}]},
      {"ID":"87","Source":"EC","Eqpmnts":[]}
    ];
    // 初始化所有item为收起状态
    this.gDatas.forEach(item => {
      this.expandedStates[item.ID] = false;
    });
  }

  toggleSection(item) {
    // 切换对应ID的展开状态
    this.expandedStates[item.ID] = !this.expandedStates[item.ID];
  }
}

模板代码修改

模板里绑定expandedStates[item.ID]来控制元素显示和按钮样式:

<ion-row *ngFor="let item of gDatas">
  <ion-col col-1>
    <button (click)="toggleSection(item)" detail-none 
            [ngClass]="{'section-active1': expandedStates[item.ID], 'section1': !expandedStates[item.ID]}">
      <ion-icon item-left name="arrow-dropright" *ngIf="!expandedStates[item.ID]"></ion-icon>
      <ion-icon item-left name="arrow-dropdown" *ngIf="expandedStates[item.ID]"></ion-icon>
    </button>
  </ion-col>
  <ion-col col-2>
    <ion-input type="number" [(ngModel)]="item.ID" text-wrap></ion-input>
  </ion-col>
  <ion-col col-2>
    <ion-label>{{item.Source}} </ion-label>
  </ion-col>
  <div *ngIf="expandedStates[item.ID]">
    <ion-grid >
      <ion-row *ngFor="let eqpm of item.Eqpmnts" nowrap>
        <ion-col>
          <ion-label>{{eqpm.ID}} </ion-label>
          <ion-label>{{eqpm.CreatedBy}} </ion-label>
        </ion-col>
      </ion-row>
    </ion-grid>
  </div>
</ion-row>

这两种方案的核心都是让每个列表项拥有独立的状态变量,不再共享全局变量,这样点击某一行的按钮时,只会修改当前行对应的状态,完美实现你要的“仅展开当前行详情”的效果。

内容的提问来源于stack exchange,提问作者Jayesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:06:12