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

基于Bootstrap实现自定义表头与叶子节点的动态嵌套手风琴

实现自定义交互的Bootstrap嵌套手风琴

要实现仅右侧切换按钮控制展开/收起,表头主体点击触发独立事件的需求,核心是把「折叠触发」和「表头点击事件」拆分成两个独立的交互区域,剥离Bootstrap默认的全表头触发折叠行为。以下是具体修改方案:

关键修改思路

  • 拆分原表头按钮:将单个按钮拆分为「表头内容容器」和「独立切换按钮」,各自绑定对应事件
  • 转移Bootstrap折叠属性:把data-bs-toggle、data-bs-target从原表头按钮移到右侧切换按钮上
  • 布局调整:用Flex布局让切换按钮固定在表头右侧,保证交互区域清晰

修改后的完整代码

<div class="accordion" [attr.id]="entityName">
  <div class="accordion-item">
    <div class="pageNameTab mb-1" [id]="'heading-'+ entityName">
      <ng-container *ngIf="!children || children.length === 0; else hasChildrenBlock">
        <!-- 叶子节点保持原结构 -->
        <button class="pageButton col-12 btn rounded-0 text-left"
                (click)="onVeClick(entityName)"
                [ngClass]="entityName === selectedVe ? 'btn-light-primary' : ''">
          <div class="row mb-0 pb-1">
            <div class="col-10 d-flex">
              {{entityName}}
            </div>
          </div>
        </button>
      </ng-container>
      <ng-template #hasChildrenBlock>
        <!-- 带子节点的表头:拆分为内容容器 + 切换按钮 -->
        <div class="pageButton col-12 btn rounded-0 text-left d-flex align-items-center justify-content-between"
             [ngClass]="entityName === selectedVe ? 'btn-light-primary' : ''"
             (click)="onVeClick(entityName)">
          <!-- 表头内容区域 -->
          <div class="d-flex">
            {{ entityName }}
          </div>
          <!-- 独立的折叠切换按钮 -->
          <button class="btn btn-link p-0"
                  data-bs-toggle="collapse"
                  [attr.data-bs-target]="'#'+entityName+'-1'"
                  [attr.aria-controls]="entityName+'-1'"
                  (click)="$event.stopPropagation()"> <!-- 阻止冒泡,避免触发表头的onVeClick -->
            <!-- 可添加折叠图标,比如Bootstrap内置图标 -->
            <i class="bi bi-chevron-down"></i>
          </button>
        </div>
      </ng-template>
    </div>
    <div *ngIf="children && children.length > 0">
      <div [id]="entityName+'-1'" class="accordion-collapse collapse"
           [attr.aria-labelledby]="'heading-'+ entityName" 
           [attr.data-bs-parent]="'#'+ entityName">
        <div class="accordion-body pt-2 pb-0 pr-0">
          <app-accordian-item *ngFor="let child of children" 
                              [entityName]="child.entityName"
                              [children]="child.children" 
                              [selectedVe]="selectedVe" 
                              (itemClick)="onChildItemClick($event)">
          </app-accordian-item>
        </div>
      </div>
    </div>
  </div>
</div>

核心修改点说明

  • 拆分交互区域:将原单个按钮改为div容器作为表头主体,绑定onVeClick事件;右侧新增独立按钮专门负责折叠切换
  • 阻止事件冒泡:切换按钮的点击事件添加$event.stopPropagation(),避免点击切换按钮时触发表头的onVeClick事件
  • 布局优化:用d-flex align-items-center justify-content-between让表头内容左对齐、切换按钮右对齐,符合用户交互预期
  • 保留Bootstrap折叠能力:通过转移data-bs-*属性,继续利用Bootstrap原生折叠组件的逻辑,无需额外手写大量JS代码

可选:手动控制折叠状态(适配复杂场景)

如果需要通过组件逻辑主动控制折叠状态(比如根据业务规则自动展开/收起),可以用Angular的ViewChild获取Bootstrap Collapse实例:

  1. 组件类中引入并初始化:
import { ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import Collapse from 'bootstrap/js/dist/collapse';

export class AccordianItemComponent implements AfterViewInit {
  @ViewChild('collapseElement') collapseElement!: ElementRef;
  private collapseInstance?: Collapse;

  ngAfterViewInit() {
    this.collapseInstance = new Collapse(this.collapseElement.nativeElement);
  }

  toggleCollapse() {
    this.collapseInstance?.toggle();
  }
}
  1. 对应修改模板:
<!-- 切换按钮 -->
<button class="btn btn-link p-0"
        (click)="toggleCollapse(); $event.stopPropagation()">
  <i class="bi bi-chevron-down"></i>
</button>

<!-- 折叠容器 -->
<div #collapseElement [id]="entityName+'-1'" class="accordion-collapse collapse"
     [attr.aria-labelledby]="'heading-'+ entityName" 
     [attr.data-bs-parent]="'#'+ entityName">

这种方式可以完全通过组件逻辑控制折叠状态,适配更复杂的业务需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:47:04