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?
source to share
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>
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
.
source to share