我真的很喜欢为Dynamic template based on value rather than variable with ngTemplateOutlet提供的答案。但是,我无法使其正常工作。简化示例:
export class A {
}
export class MyComponent
implements OnInit {
public controls$ = Observable<any[]>([]);
ngOnInit() {
this.controls$.next([new A()]);
}
public getTypeName(control: any) {
if (control instanceof A) {
return "AControl";
}
return "";
}
}
模板:
<div *ngFor="let control of control$ | async">
{{ getControlType(control) }}
</div>
收益:
AControl
到目前为止,一切都很好。添加模板时,出现异常:
<div *ngFor="let control of control$ | async">
{{ getControlType(control) }}
<ng-container
[ngTemplateOutlet]="getControlType(control)"
[ngTemplateOutletContext]="{ control: control }">
</ng-container>
</div>
<ng-template
#AControl
let-item="control">A Control</ng-template>
抛出:
templateRef.createEmbeddedView不是函数
我不确定为了使模板#AControl
能够在容器中呈现,我需要更改什么。
答案 0 :(得分:1)
似乎是[ngTemplateOutlet]="getControlType(control)"
的元凶。我没有看到getControlType()
的代码,但是我想它正在返回s字符串,而它应该是一个TemplateRef
对象。除非您使用ChangeDetectionStrategy.OnPush
,否则在模板中调用函数不是一个好主意,因此建议您在模板中使用switch语句。不过,
@ViewChild("AControl", {static: true})
AControl: TemplateRef<any>;
您可以访问.ts文件中的模板,然后从getControlType函数返回
答案 1 :(得分:0)
在我发现的D Pro's Answer的帮助下,我真的不需要在实例中使用ngTemplateOutlet
(对于像我使用的简单事物来说,它们似乎真的很复杂)。 / p>
我的最终解决方案是:
打字稿
export class A {
}
export class B {
}
export class MyComponent
implements OnInit {
public controlsTypes$ = Observable<any[]>([]);
ngOnInit() {
var value1 = new A();
var value2 = new B();
this.controls$.next([
{ control: value1, type: getTypeName(value1)},
{ control: value2, type: getTypeName(value2)},
]);
}
public getTypeName(control: any) {
if (control instanceof A) {
return "AControl";
} else if (control instanceof B) {
return "BControl";
}
return "";
}
public onClick(control: any) {
}
}
html:
<div *ngFor="let controlType of controlType$ | async"
[ngSwitch]="controlType.type">
<ng-template ngSwitchCase="AControl">
<div (click)="onClick(controlType.control)">{{ controlType.type }}</div>
</ng-template>
<ng-template ngSwitchCase="BControl">
<div (click)="onClick(controlType.control)">{{ controlType.type }}</div>
</ng-template>
</div>
同时显示AControl
和BControl
,并在单击它们时将实例化的类传递给onClick()
。