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

时间:2017-06-01 18:18:58

标签: angular typescript

我有一个基本组件( MyBaseComponent )从其调用者( App )接收数据。

我想知道我的基本组件是否有可能被其调用者告知显示'它应该使用的组件 - MyDisplayComponent MyOtherDisplayComponent

即,我想做一些事情:

<my-base [data]="names">
    <my-other-display></my-other-display>
</my-base>

并在不同的位置,例如:

<my-base [data]="names">
    <my-display></my-display>
</my-base>

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

Here's a working Plunker,下面列出的代码,希望传达我尝试的内容。

app.ts

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 {}

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() {
  }
}

我-display.component.ts

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

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

  constructor() {
  }
}

我-另一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() {
  }
}

再一次,大问题&#39;以下是否可以在 app.ts (调用程序)级别指定display组件,以便 my-base.component.ts < / strong>文件可能不知道在给定情况下使用的具体实现。

可能 my-base.component.ts 文件需要传递一个类名或要使用的类型来粘贴某种界面......?

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

您可以使用ngComponentOutlet来选择组件,可能ngIf或切换以显示,我不确定您的用途。

Plunker

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

 // in module
entryComponents : [ MyDisplayComponent, MyOtherDisplayComponent],

答案 1 :(得分:2)

1)您可以尝试使用ngTemplateOutlet指令,如

我-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[];
}

<强> app.component.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"];
}

<强> Forked Plunker

2)使用ngForTemplate

中只有一个区别的方法几乎相同

我-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[];
}

<强> Forked Plunker ngForTemplate

答案 2 :(得分:1)

而不是ng-content,您只需使用if和else解决。

基本组件将传递true或false值以呈现

<强> app.ts

 <my-base [data]="names" [isValid]=false>

<强> MyBaseComponent.ts

 <div *ngIf="isValid;then content else other_content"></div>

<ng-template #content> <div *ngFor="let datum of data"> 
    <my-display [value]="datum"></my-display>
  </div></ng-template>
<ng-template #other_content> <div *ngFor="let datum of data">

    <my-other-display [value]="datum"></my-other-display>
  </div></ng-template>

答案 3 :(得分:-1)

如果我理解正确,你可以使用NgSwitch

<div [ngSwitch]="typeOfComponent">
  <my-display  [value]="datum" *ngSwitchCase="type1"></my-other-display>
  <my-other-display  [value]="datum" *ngSwitchCase="type2"></my-other-display>
  <my-other-display  [value]="datum" *ngSwitchCase="type3"></my-other-display>      
</div>