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

Angular Mat如何实现打开其他Expansion Panel时关闭已开面板

问题原因

你现在的实现里每个交易条目都单独套了一个独立的<mat-accordion>实例,Angular Material默认的multi="false"互斥展开逻辑仅对同一个accordion标签内部的面板生效,跨独立accordion的面板状态完全不互通;再加上每个单条组件自己维护showHistory展开状态,组件之间没有任何通信,自然无法实现打开新面板自动关闭旧面板的效果。
另外你现在自定义的点击箭头切换showHistory的逻辑,和MatExpansionPanel自带的展开状态控制是冲突的,额外加的*ngIf="showHistory"也会破坏组件自带的展开动画和状态同步。

解决方案

方案1(推荐,改造成本最低)

把<mat-accordion>标签移到所有交易条目的外层父组件中,所有<mat-expansion-panel>都作为这个唯一accordion的子元素,不需要写任何自定义状态控制逻辑,原生就支持互斥展开:

  • 父组件(循环渲染交易列表的组件)中放置唯一的<mat-accordion>,默认multi="false"(不写配置默认就是这个值,自动开启互斥)
  • 在accordion内部通过*ngFor循环渲染所有<mat-expansion-panel>,把你原来单条组件里的面板头、详情内容直接放到对应panel标签内
  • 删除单条组件里自定义的showHistory变量、fetchHistoryDetails点击事件、详情区的*ngIf="showHistory"控制,面板的展开收起完全交给Angular Material组件自身处理,需要加载详情的逻辑可以绑定面板的opened事件触发。

改完的父组件HTML示例:

<mat-accordion>
  <mat-expansion-panel *ngFor="let transactionDTO of transactionList" (opened)="fetchHistoryDetails(transactionDTO)">
    <mat-expansion-panel-header>
      <div
        class="col text-center"
        [ngClass]="{
          'text-green': transactionDTO.txn_type == 'CREDIT',
          'text-red': transactionDTO.txn_type == 'DEBIT',
          'text-cyan': transactionDTO.txn_type == 'WITHDRAWAL'
        }"
      >
        {{ transactionDTO.txn_type }}
      </div>
      <div class="col text-center" style="font-size: 20px;">
        {{ transactionDTO.created_date | date: "dd-MMM-yyyy" }}
      </div>
      <div class="text-center col-xl">
        {{ transactionDTO.txn_status }}
      </div>
      <div class="col text-center" style="font-size: 20px;">
        <span
          [ngClass]="{
            'text-green': transactionDTO.txn_type == 'CREDIT',
            'text-red': transactionDTO.txn_type == 'DEBIT',
            'text-cyan': transactionDTO.txn_type == 'WITHDRAWAL'
          }"
          ><ng-container
            *ngIf="
              transactionDTO.txn_type == 'WITHDRAWAL' ||
                transactionDTO.txn_type == 'DEBIT';
              else credit
            "
            >-</ng-container
          ><ng-template #credit>+</ng-template
          >{{ transactionDTO.txn_amount | currency: "USD":"":"1.2-2" }}</span
        >
      </div>
      <div class="col text-center" style="font-size: 20px;">
        {{ transactionDTO.final_amount | currency: "USD":"":"1.2-2" }}
      </div>
      <div class="col text-center downarrow">
        {{
          transactionDTO.payment_method == "Wire transfer"
            ? transactionDTO.txn_id
            : transactionDTO.payment_method
        }}
      </div>
    </mat-expansion-panel-header>
    <div
      class="row detailsRow no-gutters justofy-content-around align-items-center"
      marketplace-transaction-history-details
      [transactionType]="transactionDTO.transactionType"
      [userType]="'BUYER'"
      [currentStatusStep]="transactionDTO.currentStatus"
    ></div>
  </mat-expansion-panel>
</mat-accordion>

原来的CSS里.mat-accordion .mat-expansion-panel:last-of-type的选择器去掉:last-of-type,不然只有最后一个面板会应用边框样式,其他面板样式会异常。

方案2(需要保留单条组件独立封装时使用)

如果必须保留单条组件独立包裹的结构,就通过父组件统一管理当前激活的面板ID,实现跨组件状态同步:

  1. 父组件维护变量activePanelId: string | number = null,存储当前展开面板的唯一标识(用txn_id即可)
  2. 给每个单条组件传入两个参数:当前条目的唯一ID、全局激活的activePanelId,同时绑定单条组件抛出的面板切换事件
  3. 单条组件内通过计算属性判断自身是否应该展开,点击面板时把自身ID发射给父组件,父组件更新activePanelId后,其他所有条目的状态会自动切换为收起。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:33:22