Angular 2:如何为字符串数组的每个字段传递对应模板
解决Angular中字符串数组字段与模板匹配的问题
我明白你遇到的困扰了——当字段名包含点号(比如person.age)时,直接用[ngTemplateOutlet]="field"根本找不到对应的模板,而且带点的模板引用变量本身就是无效的Angular语法。下面给你一步步的解决方案:
问题根源
- Angular的模板引用变量(比如
#name)不允许包含点号,所以你写的<ng-template #person.age>其实是无效的,Angular根本识别不了这个引用。 - 当你把字符串
'person.age'传给ngTemplateOutlet时,Angular会尝试把它解析成组件的属性路径(比如this.person.age),而不是去找对应的模板引用,自然匹配失败。
解决方案:用映射关联字段与模板
我们可以创建一个字段名到模板引用的映射对象,这样不管字段名是什么格式,都能精准匹配到对应的模板。
步骤1:修改模板引用变量(去掉点号)
先把带点的模板名改成合法的格式,比如:
<ng-template #name> Name template </ng-template> <ng-template #createdAt> Created at template </ng-template> <ng-template #personAge> person.age template </ng-template>
步骤2:在组件中定义映射关系并获取模板引用
在TS代码里,用ViewChild获取每个模板的引用,然后创建映射对象:
import { Component, ViewChild, TemplateRef } from '@angular/core'; @Component({ selector: 'app-my-component', templateUrl: './my-component.component.html' }) export class MyComponent { fields = ['name', 'person.age', 'created_at']; // 获取每个模板的引用 @ViewChild('name') nameTemplate!: TemplateRef<any>; @ViewChild('createdAt') createdAtTemplate!: TemplateRef<any>; @ViewChild('personAge') personAgeTemplate!: TemplateRef<any>; // 创建字段到模板的映射 fieldTemplateMap: Record<string, TemplateRef<any>> = { 'name': this.nameTemplate, 'person.age': this.personAgeTemplate, 'created_at': this.createdAtTemplate }; }
步骤3:在模板中通过映射获取对应模板
修改ngTemplateOutlet的绑定,从映射中取对应的模板:
<div *ngFor="let field of fields"> <ng-container [ngTemplateOutlet]="fieldTemplateMap[field]"> </ng-container> </div>
进阶方案:动态获取所有模板(适合字段较多的场景)
如果你的字段和模板数量很多,手动写ViewChild太麻烦,可以用ViewChildren结合模板的自定义属性来批量映射:
模板代码:
给每个模板加一个自定义属性fieldName,用来标记对应的字段:
<div *ngFor="let field of fields"> <ng-container [ngTemplateOutlet]="getTemplateForField(field)"> </ng-container> </div> <ng-template #name [fieldName]="'name'"> Name template </ng-template> <ng-template #createdAt [fieldName]="'created_at'"> Created at template </ng-template> <ng-template #personAge [fieldName]="'person.age'"> person.age template </ng-template>
TS代码:
import { Component, ViewChildren, QueryList, TemplateRef, ElementRef } from '@angular/core'; @Component({ selector: 'app-my-component', templateUrl: './my-component.component.html' }) export class MyComponent { fields = ['name', 'person.age', 'created_at']; @ViewChildren(TemplateRef) templates!: QueryList<TemplateRef<any>>; getTemplateForField(field: string): TemplateRef<any> | undefined { return this.templates.find(tpl => { // 获取模板的fieldName属性值 const element = tpl.elementRef.nativeElement as HTMLElement; return element.getAttribute('fieldName') === field; }); } }
这样不管你新增多少字段和模板,只要给模板加上对应的fieldName属性,就能自动匹配,不用手动维护映射对象。
内容的提问来源于stack exchange,提问作者Shrakka
相关产品推荐
相关产品推荐

