通过将组件名称指定为输入参数,将 Angular 组件导入另一个组件

Import Angular Component into another Component by specifying the component name as input parameter

我想创建一个由多个子组件组成的角度组件。最终我想创建一个大型可重用树组件,其节点具有不同的数据类型。对于每种数据类型,树组件导入指定节点显示方式的子组件。用户应该能够指定自定义组件来覆盖特定数据类型的默认组件。像这样的导入语法会很好:

<app-tree [customDateComp]="CustomDateComponent"></app-tree>

这可能是简化的 tree.component.html:

<ng-container *ngIf="!customDateComp">
 <app-default-date></app-default-date>
</ng-container>
<ng-container *ngIf="customDateComp">
 {{ customDateComp }}
</ng-container>

当然这还不行,因为组件是用语法导入的。下面的方法也不起作用,因为 angular 转义了它:

<app-tree [customDateComp]="'<app-custom-date></app-custom-date>'"></app-tree>

示例代码可以在这里找到: https://stackblitz.com/edit/angular-ivy-xghj5f?file=src/app/app.component.html

有谁知道如何通过将组件名称指定为输入参数来将 Angular 组件导入其他组件?或者有没有更好的方法来覆盖第三方组件的默认子组件?非常感谢!

这是你的stackblitz demo作品。

在可能的方法中,有一个门户(以及 @angular/cdk/portal 提供的实用程序)。

基本上,这就是您需要的:

1 - 接收组件的占位符(在本例中为 cdkPortalOutlet 设置):

<ng-template [cdkPortalOutlet]="_compPortal"></ng-template>

2 - 一个门户(_compPortal,上图)插入你的门户出口:

_compPortal = new ComponentPortal<any>(MyCustomComponent);

就这些了。

在你的情况下(你在问题中链接的 stackblitz)你可以这样做:

0 - 导入 @angular/cdk/portal 模块:

import {PortalModule} from '@angular/cdk/portal';

@NgModule({imports: [ ... PortalModule ] ...}) export class AppModule { }

1 - tree.component.html

<ng-container *ngIf="!_compPortal">
 <app-date></app-date>
</ng-container>
<ng-container *ngIf="_compPortal">
  <ng-template [cdkPortalOutlet]="_compPortal"></ng-template>
</ng-container>

2 - tree.compoenent.ts

@Input() 
set customDateComp(customComp: any){
  this._compPortal = customComp ? new ComponentPortal(customComp) : null;
}
_compPortal: ComponentPortal<any>;

3 - app.component.ts

// Notice this is not `_comp: CustomDateComponent`.
// I'm setting up an attribute that receives the type so I can 
// make it available on the template
_comp = CustomDateComponent;

4 - app.component.html

<app-tree [customDateComp]="_comp"></app-tree>

您可以使用动态组件加载器https://angular.io/guide/dynamic-component-loader