在Ag-Grid自定义单元格中添加Bootstrap弹窗失败求助
Ag-Grid单元格自定义组件中Bootstrap模态框无法显示的解决方案
问题核心原因
- 原生Bootstrap模态框依赖jQuery和Popper.js,Angular环境中若未正确引入或使用方式不当,会导致
data-toggle等属性失效。 - Ag-Grid单元格组件被包裹在Grid容器内,容器可能设置了
overflow: hidden或较低的z-index,导致模态框被遮挡或无法渲染到可视区域。 - 模态框DOM位于单元格组件内部,Ag-Grid的虚拟滚动机制可能引发组件销毁或DOM层级冲突。
方案一:改用ng-bootstrap(推荐,无jQuery依赖)
ng-bootstrap是纯Angular实现的Bootstrap组件,完全适配Angular生态,避免jQuery冲突问题。
- 安装依赖
npm install @ng-bootstrap/ng-bootstrap bootstrap
- 在
app.module.ts中导入模块
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @NgModule({ imports: [ // 其他模块 NgbModule ] }) export class AppModule { }
- 修改自定义单元格组件代码
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); } }
- 修改组件模板
<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">×</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,需确保依赖正确引入并手动控制模态框状态。
- 在
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" ]
- 修改组件代码
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'); } }
- 修改组件模板
<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">×</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容器遮挡,可将模态框放在根组件中,通过服务控制显示/隐藏。
- 创建模态框服务
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); } }
- 在
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">×</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>
- 在
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'); }); } }
- 修改自定义单元格组件
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(); } }
- 修改组件模板
<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
相关产品推荐
相关产品推荐

