Angular如何在被点击的表格td单元格内部动态创建组件
问题现象
现有代码运行后,动态生成的MyComponent会被追加到</table>闭合标签之后,与预期不符。预期效果为将MyComponent动态创建并插入到用户点击的对应表格单元格(即<td>标签内部)。
原代码文件:
some.component.html
<table> <tr *ngfor="let row in table"> <td *ngFor="let cell in row" (click)="onCellClick($event)">Cell Text</td> </tr> </table>
组件逻辑代码
@Component({ selector: 'app-my-component', template: '<div>My Component</div>', }) export class MyComponent { } @Component({ selector: 'app-some', templateUrl: './some.component.html' }) export class SomeComponent { public table = [[1, 2, 3], [4, 5, 6]]; constructor( private viewContainerRef: ViewContainerRef ) { } onCellClick(event: MouseEvent): void { const myComponent = this.viewContainerRef.createComponent(MyComponent); } }
问题原因
构造函数中注入的ViewContainerRef绑定的是SomeComponent本身的宿主视图容器,默认位置就是组件模板的最末尾,所以在这个容器上创建的动态组件,会被追加到整个组件模板的最后(也就是table标签闭合位置之后),自然无法插入到td内部。
另外原模板的*ngFor写法存在语法错误:指令名应为大驼峰写法*ngFor,遍历数组元素需要用of关键字,in是用来遍历对象键名的,直接用在数组上会导致循环逻辑异常。
实现方案
使用Angular标准的视图容器机制实现,不需要手动操作原生DOM,框架会自动接管变更检测和组件生命周期:
- 修改模板,修复*ngFor语法问题,在每个td内部添加独立的视图容器锚点,点击时直接将对应容器传入点击事件:
<table> <tr *ngFor="let row of table"> <td *ngFor="let cell of row" (click)="onCellClick(cellContainer)"> Cell Text <!-- 每个td内部的动态组件挂载锚点 --> <ng-container #cellContainer></ng-container> </td> </tr> </table>
- 修改组件类逻辑,移除全局注入的组件级
ViewContainerRef,点击事件接收目标td对应的容器作为参数,直接在该容器上创建动态组件:
import { Component, ViewContainerRef } from '@angular/core'; // 注意替换为项目中MyComponent的实际导入路径 import { MyComponent } from './my.component'; @Component({ selector: 'app-some', templateUrl: './some.component.html' }) export class SomeComponent { public table = [[1, 2, 3], [4, 5, 6]]; constructor() { } onCellClick(targetContainer: ViewContainerRef): void { // 可选:清空当前容器之前生成的组件,避免重复点击生成多个实例 targetContainer.clear(); // 在点击的单元格容器内创建组件 const myComponentRef = targetContainer.createComponent(MyComponent); // 如果需要给动态组件传输入参数,可以直接通过实例赋值 // myComponentRef.instance.someProp = 'xxx'; } }
改完之后点击哪个td,动态生成的MyComponent就会被插入到对应td的ng-container位置,完全符合预期。
不要使用从点击事件拿原生td元素、再把组件宿主元素append到td里的写法,这种方式脱离了Angular的视图管理,需要手动处理变更检测、组件销毁逻辑,很容易引发内存泄漏或视图不更新的问题。
内容的提问来源于stack exchange,提问作者waxono7326
相关产品推荐
相关产品推荐

