Getting reference to ngComponentOutlet

I am dynamically creating a component with ngComponentOutlet. Looks 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 suppose) to get a reference to the current component to feed the data, but that failed :(

Should I use ViewContainerRef like?

+3


source to share


1 answer


You must specify the name of the component directly:

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

      

I took the liberty of adding a module that is used to render a component from a module other than the current module.

Also, to use the Module option, you 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 the current module, this is what you need to do:

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

      

NgComponentOutlet

To import a module: NgModuleFactory

Update (dynamic):

Create a vector, for example:

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 can display as many components as MY_ALERTS

.



Or you can try rendering it dynamically by creating a new one ng-container

(don't test it yet).

I use this to render components from a huge vector containing component classes with different values ​​such as booleans, so I know which component will load each time.

To render the component 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 @Pipe

that which returns the keys of the object (instead of the value) to me.

Update (alternative approach):

I thought that perhaps you might be interested in this other approach: use @Component as a "Directive". I'll explain myself:

Declare your components with a selector type directive:

@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 the case:

@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 (although untested) I am initializing a success alert. On click, it should install alertSuccess

as false

and install alertDanger

as true

.

+1


source







All Articles