Angular模板出现数据undefined错误:Kendo网格自定义模板无法识别dataItem
问题原因
你遇到的报错本质是ng-template的变量作用域规则导致的:
ng-template本身是惰性渲染的,它内部的变量优先级为:优先读取渲染模板时传入的上下文参数,如果没有显式声明let-xxx绑定上下文参数,才会继承模板定义位置的父作用域变量。- 你的代码里给自定义模板显式加了
let-dataItem="dataItem"声明,相当于强制要求Angular从模板渲染的上下文里读取dataItem,而你在app-command-menu组件内部渲染这个传入的模板时,没有给ngTemplateOutlet传入包含dataItem的上下文,因此拿到的是undefined,才会触发Cannot read properties of undefined (reading 'hpi')报错。 - 同一作用域下
app-command-menu的[hpiId]绑定能正常读取dataItem,是因为组件的输入属性绑定是直接执行在当前网格单元格的作用域下,不需要等子组件渲染模板时再取值。
解决方案
有两种可行的修复方案,可根据你的实际需求选择:
方案1:最小改动,直接移除模板的上下文声明
不需要修改app-command-menu组件,直接删掉自定义模板上的let-dataItem="dataItem"声明即可,此时模板会直接继承定义位置的网格单元格作用域的dataItem变量:
<!-- 自定义模板 移除let-dataItem声明 --> <ng-template #customMenuItemsTemplate> <button mat-menu-item *ngIf="dataItem.hpi?.id" ... > <mat-icon>...</mat-icon> </button> </ng-template>
该方案适合自定义模板仅需使用当前网格行数据的场景,改动成本最低。
方案2:子组件传入模板上下文,复用性更强
如果后续其他场景下使用app-command-menu时,传入的模板需要依赖子组件内部的状态数据,可以选择该方案:
- 给
app-command-menu新增输入属性接收当前行数据:
// app-command-menu.component.ts @Input() dataItem: any; @Input() contentTemplate: TemplateRef<any>;
- 父组件调用时给子组件传入
dataItem:
<app-command-menu [contentTemplate]="customMenuItemsTemplate" [hpiId]="dataItem.hpi.id" [dataItem]="dataItem" ... ></app-command-menu>
- 修改
app-command-menu内部渲染自定义模板的逻辑,传入上下文:
<!-- app-command-menu.component.html 菜单位置 --> <ng-container *ngIf="contentTemplate"> <ng-template [ngTemplateOutlet]="contentTemplate" [ngTemplateOutletContext]="{ dataItem: dataItem }" ></ng-template> </ng-container>
该方案更符合组件封装的最佳实践,app-command-menu的适配性更强,不依赖外层作用域的变量。
内容的提问来源于stack exchange,提问作者gib65
相关产品推荐
相关产品推荐

