如何将组件类型传递给 Angular 中的另一个组件?

Cug*_*uga 7 typescript angular

我有一个基础组件(MyBaseComponent)从它的调用者(App)。

我想知道它的调用者是否可以告诉我的基本组件它应该使用什么“显示”组件—— MyDisplayComponentMyOtherDisplayComponent

即,我想做一些事情:

<my-base [data]="names">
    <my-other-display></my-other-display>
</my-base>
Run Code Online (Sandbox Code Playgroud)

并且在不同的位置,例如:

<my-base [data]="names">
    <my-display></my-display>
</my-base>
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚如何做到这一点。我尝试了 的不同用法<ng-content>,但我认为它不能提供这种级别的灵活性。另外ComponentFactoryResolver听起来它可以工作,但我再次不确定它如何以迭代方式工作,以及将数据传递给子控件。

这是一个工作的Plunker,其代码概述如下,希望能传达我正在尝试的内容。

应用程序

import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {MyBaseComponent} from './my-base.component'
import {MyDisplayComponent} from './my-display.component'
import {MyOtherDisplayComponent} from './my-other-display.component'


@Component({
  selector: 'my-app',
  template: `
    <div>
      <my-base [data]="names">

      <!-- Is it possible to specify the 'display component' type to use here? -->

      </my-base>
    </div>
  `,
})
export class App {

  names: string[] = ["bill", "bob", "ben"];

  constructor() {
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, MyBaseComponent, MyDisplayComponent, MyOtherDisplayComponent ],
  bootstrap: [ App ]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

my-base.component.ts

import {Component, Input} from '@angular/core'

@Component({
  selector: 'my-base',
  template: `
  <div *ngFor="let datum of data">

    <!-- Instead of specifying the display components here,
    how can I specify the components type to use for display
    at the 'app.ts' level? -->

    <!--<my-display [value]="datum"></my-display>-->
    <my-other-display [value]="datum"></my-other-display>
  </div>
  `,
})
export class MyBaseComponent {

  @Input()
  data: string[];

  constructor() {
  }
}
Run Code Online (Sandbox Code Playgroud)

我的display.component.ts

import {Component, Input} from '@angular/core'

@Component({
  selector: 'my-display',
  template: `
  <div>{{value}}</div>
  `,
})
export class MyDisplayComponent {
  @Input()
  value:string;

  constructor() {
  }
}
Run Code Online (Sandbox Code Playgroud)

my-other-display.component.ts

//our root app component
import {Component, Input} from '@angular/core'

@Component({
  selector: 'my-other-display',
  template: `
  <div>{{value}}! {{value}}! {{value}}!</div>
  `,
})
export class MyOtherDisplayComponent {

  @Input()
  value:string;

  constructor() {
  }
}
Run Code Online (Sandbox Code Playgroud)

同样,这里的大“问”是是否可以指定displayapp.ts(调用者)级别使用的组件,以便my-base.component.ts文件可以忽略在给定情况下使用的特定实现.

可能是my-base.component.ts文件需要传递一个类名或一个类型来使用它遵循某种接口......?

在此先感谢您的帮助。

Dyl*_*lan 6

您也许可以使用ngComponentOutlet来选择组件,也ngIf可以切换要显示的组件,我不确定您要做什么。

普朗克

<ng-container *ngComponentOutlet="MyDisplayComponent"></ng-container>

 // in module
entryComponents : [ MyDisplayComponent, MyOtherDisplayComponent],
Run Code Online (Sandbox Code Playgroud)


yur*_*zui 3

1)您可以尝试使用ngTemplateOutlet类似指令

my-base.component.ts

@Component({
  selector: 'my-base',
  template: `
    <div *ngFor="let datum of data">
      <ng-container *ngTemplateOutlet="tmpl; context: { $implicit: datum }"></ng-container>
    </div>
  `,
})
export class MyBaseComponent {
  @ContentChild(TemplateRef) tmpl: TemplateRef<any>;

  @Input() data: string[];
}
Run Code Online (Sandbox Code Playgroud)

应用程序组件.ts

@Component({
  selector: 'my-app',
  template: `
    <my-base [data]="names">
      <ng-template let-item>
        <my-other-display [value]="item"></my-other-display>
      </ng-template>
    </my-base>

    <my-base [data]="names">
      <ng-template let-item>
        <my-display [value]="item"></my-display>
      </ng-template>
    </my-base>
  `,
})
export class App {
  names: string[] = ["bill", "bob", "ben"];
}
Run Code Online (Sandbox Code Playgroud)

叉形插头

2)使用ngForTemplate. 几乎相同的方法,只有一处不同

my-base.component.ts

@Component({
  selector: 'my-base',
  template: `<div *ngFor="let datum of data; template: tmpl"></div>`
})
export class MyBaseComponent {
  @ContentChild(TemplateRef) tmpl: TemplateRef<any>;

  @Input() data: string[];
}
Run Code Online (Sandbox Code Playgroud)

Forked Plunker ngForTemplate