根据类型渲染动态模板

时间:2019-10-28 00:28:38

标签: angular typescript angular8

我真的很喜欢为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能够在容器中呈现,我需要更改什么。

2 个答案:

答案 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>

同时显示AControlBControl,并在单击它们时将实例化的类传递给onClick()