Angular 14中如何从无父子关系的组件C打开组件A的Bootstrap模态框
问题
我正在使用Angular v14、Bootstrap 4和REST API,现有三个组件:组件A为父组件,其导航栏内设有可打开Bootstrap模态框的按钮,模态框主体包含其子组件B的选择器;另有组件C,希望通过其模板中的按钮打开组件A的模态框以展示编辑数据,以下是我的代码:
Component A 模板
<!-- modal trigger icon --> <li class="nav-item"> <a class="nav-link text-white" data-toggle="modal" data-target="#modelId" (click) = "addClick()" > <i class="fa-solid fa-rectangle-ad fa-2xl"></i> </a> </li> <div class="modal fade" id="modelId" tabindex="-1" data-backdrop="static" data-keyboard="false" role="dialog" aria-labelledby="modelTitleId" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Post Product</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <app-B [product]="product"></app-B> </div> </div> </div> </div>
Component C 模板(希望从此处打开组件A的模态框)
<td> <a class="a-trash" (click)="editClick(item)"> <i class="fa-solid fa-pen-to-square fa-xl"></i> </a> <a class="a-trash"> <i class="fa fa-trash fa-xl"></i> </a> </td>
解决方案
步骤1:创建共享模态框服务
生成一个全局服务用于传递模态框触发事件和编辑数据:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { Product } from './product.model'; // 替换为你的产品模型路径 @Injectable({ providedIn: 'root' }) export class ModalService { private openModalSubject = new Subject<Product | null>(); openModal$ = this.openModalSubject.asObservable(); // 打开编辑模态框并传递数据 openEditModal(product: Product): void { this.openModalSubject.next(product); } // 打开新增模态框 openAddModal(): void { this.openModalSubject.next(null); } }
步骤2:改造Component A
在Component A中订阅服务事件,控制模态框显示并传递数据给组件B:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { ModalService } from './modal.service'; import { Product } from './product.model'; import $ from 'jquery'; // Bootstrap 4依赖jQuery操作模态框 @Component({ selector: 'app-A', templateUrl: './component-a.component.html', }) export class ComponentA implements OnInit { product: Product | null = null; @ViewChild('modalRef') modalElement!: ElementRef; // 获取模态框DOM元素 constructor(private modalService: ModalService) {} ngOnInit(): void { // 监听模态框打开事件 this.modalService.openModal$.subscribe((targetProduct) => { this.product = targetProduct; // 切换模态框标题 const titleEl = document.querySelector('.modal-title') as HTMLElement; titleEl.textContent = targetProduct ? '编辑产品' : '发布产品'; // 触发Bootstrap模态框显示 $(this.modalElement.nativeElement).modal('show'); }); } addClick(): void { this.modalService.openAddModal(); } }
同时修改Component A模板,添加模板引用变量(移除原有的id="modelId",改用模板引用更符合Angular规范):
<!-- modal trigger icon --> <li class="nav-item"> <a class="nav-link text-white" (click) = "addClick()" > <i class="fa-solid fa-rectangle-ad fa-2xl"></i> </a> </li> <!-- 添加#modalRef模板引用变量 --> <div #modalRef class="modal fade" tabindex="-1" data-backdrop="static" data-keyboard="false" role="dialog" aria-labelledby="modelTitleId" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="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"> <app-B [product]="product"></app-B> </div> </div> </div> </div>
步骤3:改造Component C
在Component C中注入模态框服务,点击编辑按钮时触发模态框打开:
import { Component } from '@angular/core'; import { ModalService } from './modal.service'; import { Product } from './product.model'; @Component({ selector: 'app-C', templateUrl: './component-c.component.html', }) export class ComponentC { constructor(private modalService: ModalService) {} editClick(item: Product): void { // 传递当前产品数据并打开编辑模态框 this.modalService.openEditModal(item); } }
注意事项
- 确保已在
angular.json的scripts数组中配置jQuery和Bootstrap JS文件路径; - 组件B需定义
@Input() product: Product | null接收数据,实现新增/编辑逻辑切换; - 若不想依赖jQuery,可改用
ng-bootstrap库(Angular原生Bootstrap实现),避免直接操作DOM。
内容的提问来源于stack exchange,提问作者Junior Dev
相关产品推荐
相关产品推荐

