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

在Ag-Grid自定义单元格中添加Bootstrap弹窗失败求助

Ag-Grid单元格自定义组件中Bootstrap模态框无法显示的解决方案

问题核心原因

  1. 原生Bootstrap模态框依赖jQuery和Popper.js,Angular环境中若未正确引入或使用方式不当,会导致data-toggle等属性失效。
  2. Ag-Grid单元格组件被包裹在Grid容器内,容器可能设置了overflow: hidden或较低的z-index,导致模态框被遮挡或无法渲染到可视区域。
  3. 模态框DOM位于单元格组件内部,Ag-Grid的虚拟滚动机制可能引发组件销毁或DOM层级冲突。

方案一:改用ng-bootstrap(推荐,无jQuery依赖)

ng-bootstrap是纯Angular实现的Bootstrap组件,完全适配Angular生态,避免jQuery冲突问题。

  1. 安装依赖
npm install @ng-bootstrap/ng-bootstrap bootstrap
  1. 在app.module.ts中导入模块
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

@NgModule({
  imports: [
    // 其他模块
    NgbModule
  ]
})
export class AppModule { }
  1. 修改自定义单元格组件代码
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ICellRendererAngularComp, ICellRendererParams } from 'ag-grid-angular';

export class CustomComponent implements ICellRendererAngularComp {
  activeValue: any;

  constructor(private modalService: NgbModal) { }

  agInit(params: ICellRendererParams<any, any>): void {
    this.activeValue = params.data.City;
  }

  refresh(params: ICellRendererParams<any, any>): boolean {
    this.activeValue = params.data.City;
    return true;
  }

  openModal(content: any) {
    this.modalService.open(content);
  }
}
  1. 修改组件模板
<div *ngIf="activeValue == 'Bangalore' else inActive">
    <button class="btn btn-secondary" (click)="openModal(content)">
        <img src="../../assets/water-drop.png" alt="">
        <span class="badge badge-dark">2</span>
    </button>
</div>

<ng-template #inActive>
    <div>
        <button class="btn btn-secondary" disabled>
            <img src="../../assets/water-drop.png" alt="">
        </button>
    </div>
</ng-template>

<ng-template #content>
  <div class="modal-header">
    <h4 class="modal-title">Modal title</h4>
    <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    ...
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary" (click)="modal.close('Close click')">Close</button>
    <button type="button" class="btn btn-primary">Save changes</button>
  </div>
</ng-template>

方案二:手动初始化原生Bootstrap模态框

若坚持使用原生Bootstrap,需确保依赖正确引入并手动控制模态框状态。

  1. 在angular.json中配置脚本依赖
"scripts": [
  "node_modules/jquery/dist/jquery.min.js",
  "node_modules/popper.js/dist/umd/popper.min.js",
  "node_modules/bootstrap/dist/js/bootstrap.min.js"
]
  1. 修改组件代码
import { ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { ICellRendererAngularComp, ICellRendererParams } from 'ag-grid-angular';
declare var $: any;

export class CustomComponent implements ICellRendererAngularComp, AfterViewInit {
  activeValue: any;
  @ViewChild('exampleModal') modalRef!: ElementRef;

  constructor() { }

  ngAfterViewInit(): void {
    $(this.modalRef.nativeElement).modal({ show: false });
  }

  agInit(params: ICellRendererParams<any, any>): void {
    this.activeValue = params.data.City;
  }

  refresh(params: ICellRendererParams<any, any>): boolean {
    this.activeValue = params.data.City;
    return true;
  }

  openModal() {
    $(this.modalRef.nativeElement).modal('show');
  }
}
  1. 修改组件模板
<div *ngIf="activeValue == 'Bangalore' else inActive">
    <button class="btn btn-secondary" (click)="openModal()">
        <img src="../../assets/water-drop.png" alt="">
        <span class="badge badge-dark">2</span>
    </button>
</div>

<ng-template #inActive>
    <div>
        <button class="btn btn-secondary" disabled>
            <img src="../../assets/water-drop.png" alt="">
        </button>
    </div>
</ng-template>

<div #exampleModal class="modal fade" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          ...
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div>
    </div>
  </div>

方案三:将模态框移至根组件,通过服务触发

若模态框被Ag-Grid容器遮挡,可将模态框放在根组件中,通过服务控制显示/隐藏。

  1. 创建模态框服务
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class ModalService {
  private modalSubject = new Subject<boolean>();
  modalState$ = this.modalSubject.asObservable();

  openModal() {
    this.modalSubject.next(true);
  }

  closeModal() {
    this.modalSubject.next(false);
  }
}
  1. 在app.component.html中添加模态框
<!-- 根组件其他内容 -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          ...
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div>
    </div>
  </div>
  1. 在app.component.ts中订阅服务
import { Component, OnInit } from '@angular/core';
import { ModalService } from './modal.service';
declare var $: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  constructor(private modalService: ModalService) {}

  ngOnInit(): void {
    this.modalService.modalState$.subscribe(state => {
      state ? $('#exampleModal').modal('show') : $('#exampleModal').modal('hide');
    });
  }
}
  1. 修改自定义单元格组件
import { ModalService } from '../modal.service';
import { ICellRendererAngularComp, ICellRendererParams } from 'ag-grid-angular';

export class CustomComponent implements ICellRendererAngularComp {
  activeValue: any;

  constructor(private modalService: ModalService) { }

  agInit(params: ICellRendererParams<any, any>): void {
    this.activeValue = params.data.City;
  }

  refresh(params: ICellRendererParams<any, any>): boolean {
    this.activeValue = params.data.City;
    return true;
  }

  openModal() {
    this.modalService.openModal();
  }
}
  1. 修改组件模板
<div *ngIf="activeValue == 'Bangalore' else inActive">
    <button class="btn btn-secondary" (click)="openModal()">
        <img src="../../assets/water-drop.png" alt="">
        <span class="badge badge-dark">2</span>
    </button>
</div>

<ng-template #inActive>
    <div>
        <button class="btn btn-secondary" disabled>
            <img src="../../assets/water-drop.png" alt="">
        </button>
    </div>
</ng-template>

内容的提问来源于stack exchange,提问作者cloud.009

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:06:16