Getting reference of ngComponentOutlet

删除回忆录丶 提交于 2019-12-23 14:01:46

问题


I'm creating dynamically a component with ngComponentOutlet. Sounds like:

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

In changeComponent(), I try (naively I guess) to get the reference of the current component to feed it with data, but it failed :(

Should I have to use ViewContainerRef, how?


回答1:


You have to put the component name directly there:

<ng-container *ngComponentOutlet="AlertDangerComponent;
            ngModuleFactory: alertDangerModule;"></ng-container>

I took the liberty to add the Module, is used for when you render a component from a Module different from the current Module.

Also, for using the Module option, you'll need this in your current component:

private alertDangerModule: NgModuleFactory<any>;

constructor(private compiler: Compiler) {
      this.alertDangerModule = compiler.compileModuleSync(AlertDangerModule);
}

If you just want to load 1 component from current Module, this is what you need to do:

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

NgComponentOutlet

For importing Module: NgModuleFactory

Update (Dynamic):

Create a vector, such as:

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

export const MY_ALERTS = {
    'alertDanger': AlertDangerComponent,
    'alertSuccess': AlertSuccessComponent,
};

In your component, you import MY_ALERTS, and you could render as many components as MY_ALERTS has.

Or you could try render it dynamically, by creating a new ng-container (Haven't test this yet).

I'm using this to render components from a huge vector containing component classes with other values such as booleans so I know which component to load each time.

To render a component that is inside this vector you can:

<div *ngFor="let alert of MY_ALERTS | keys">
        <ng-container *ngComponentOutlet="MY_ALERTS[alert];
                 ngModuleFactory: commonAlertsModule;"></ng-container>
</div>

Where keys is just a @Pipe that returns me the keys of an object (instead of the value).

Update (Alternative approach):

I was thinking that maybe you could be interested on this other approach: Use a @Component as a 'Directive'. I'll explain myself:

Declare your Components with a directive like selector:

@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...';
}

Then, you just call one or the other, depending on occasion:

@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;
  }
}

In my example (not tested though) I initialize the Success Alert. On click, It should set alertSuccess as false and set alertDanger as true.




回答2:


I've had the same issue and did some reading. The Angular world changes fast. This seems like the most official approach in the Angular guide as of this writing. See this cookbook recipe:

Angular Dynamic Component Loader

It makes use of an 'anchor' directive to tell Angular where the dynamic components will go in the template. Then it goes on to use a component factory and a view container ref to create and insert the dynamic component and while saving the instance of the newly added component.



来源:https://stackoverflow.com/questions/44584649/getting-reference-of-ngcomponentoutlet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!