获取 ngComponentOutlet 的参考

Ste*_*tef 5 components angular

我正在使用 ngComponentOutlet 动态创建一个组件。听起来好像:

import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'alert-success',
  template: `
    <p>Alert success</p>
  `,
})
export class AlertSuccessComponent {  }

@Component({
  selector: 'alert-danger',
  template: `
    <p>Alert danger</p>
  `,
})
export class AlertDangerComponent {
  test = 'danger...';
}

@Component({
  selector: 'my-app',
  template: `
    <h1>Angular version 4</h1>
    <ng-container *ngComponentOutlet="alert"></ng-container>
    <button (click)="changeComponent()">Change component</button>
  `,
})
export class App {
  alert = AlertSuccessComponent;

  changeComponent() {
    this.alert = AlertDangerComponent;
    alert(this.alert.test);       <-- ???????
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, AlertSuccessComponent, AlertDangerComponent ],
  entryComponents: [AlertDangerComponent, AlertSuccessComponent],
  bootstrap: [ App ]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

在 changeComponent() 中,我尝试(我天真地猜测)获取当前组件的引用以向其提供数据,但它失败了 :(

我应该使用 ViewContainerRef,如何使用?

SrA*_*Axi 2

您必须直接将组件名称放在那里:

<ng-container *ngComponentOutlet="AlertDangerComponent;
            ngModuleFactory: alertDangerModule;"></ng-container>
Run Code Online (Sandbox Code Playgroud)

我冒昧地添加了模块,用于当您从与当前模块不同的模块渲染组件时。

此外,为了使用 Module 选项,您将需要在当前组件中使用它:

private alertDangerModule: NgModuleFactory<any>;

constructor(private compiler: Compiler) {
      this.alertDangerModule = compiler.compileModuleSync(AlertDangerModule);
}
Run Code Online (Sandbox Code Playgroud)

如果您只想从当前模块加载 1 个组件,则需要执行以下操作:

<ng-container *ngComponentOutlet="AlertDangerComponent"></ng-container>
Run Code Online (Sandbox Code Playgroud)

NgComponentOutlet

用于导入模块:NgModuleFactory

更新(动态):

创建一个向量,例如:

import AlertDangerComponent from './path';
import AlertSuccessComponent from './path';

export const MY_ALERTS = {
    'alertDanger': AlertDangerComponent,
    'alertSuccess': AlertSuccessComponent,
};
Run Code Online (Sandbox Code Playgroud)

在您的组件中,您导入MY_ALERTS,并且可以渲染尽可能多的组件MY_ALERTS

或者您可以尝试通过创建一个新的ng-container (尚未测试)来动态渲染它。

我使用它来渲染来自一个巨大向量的组件,该向量包含具有其他值(例如布尔值)的组件类,因此我知道每次要加载哪个组件。

要渲染此向量内的组件,您可以:

<div *ngFor="let alert of MY_ALERTS | keys">
        <ng-container *ngComponentOutlet="MY_ALERTS[alert];
                 ngModuleFactory: commonAlertsModule;"></ng-container>
</div>
Run Code Online (Sandbox Code Playgroud)

其中keysa 只是@Pipe返回对象的键(而不是值)

更新(替代方法):

我在想也许您可能对另一种方法感兴趣:使用 @Component 作为“指令”。我会解释一下自己:

使用选择器之类的指令声明您的组件:

@Component({
  selector: '[alert-success]',
  template: `
    <p>Alert success</p>
  `,
})
export class AlertSuccessComponent {  }

@Component({
  selector: '[alert-danger]',
  template: `
    <p>Alert danger</p>
  `,
})
export class AlertDangerComponent {
  test = 'danger...';
}
Run Code Online (Sandbox Code Playgroud)

然后,您只需根据情况调用其中一个即可:

@Component({
  selector: 'my-app',
  template: `
    <h1>Angular version 4</h1>
    <div *ngIf="alertDanger" alert-danger></div>
    <div *ngIf="alertSuccess" alert-success></div>
    <button (click)="changeComponent()">Change component</button>
  `,
})
export class App {
  alertSuccess = true;
  alertDanger = false;

  changeComponent() {
    this.alertSuccess = !this.alertSuccess;
    this.alertDanger = !this.alertDanger;
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的示例中(尽管未测试)我初始化了成功警报。单击时,它应该设置alertSuccessfalse并设置alertDangertrue