NGX Dynamic
Best way to quickly use Dynamic Components with Angular
Example Usage
Use like NgComponentOutlet
but with @Input/@Output
auto bindings:
<ng-container *ngxComponentOutlet="component"></ng-container>
Comparison
Feature | NgxComponentOutlet | ComponentFactoryResolver | NgComponentOutlet |
---|
Friendliness | ⭐⭐⭐ | ⭐ | ⭐⭐ |
Dynamic Components | ✅ | ✅ | ✅ |
AOT support | ✅ | ✅ | ✅ |
Reactivity | ✅ | ✅ | ✅ |
Injector | ✅ | ✅ | ✅ |
NgModule | ✅ | ✅ | ✅ |
projectionNodes | ✅ | ✅ | ✅ |
Component Access | ✅ | ✅ | ❌ |
Lifecycle OnChanges | ✅ | ⭕️ manually | ❌ |
Binding @Input() | ✅ | ⭕️ manually | ❌ |
Binding @Output() | ✅ | ⭕️ manually | ❌ |
Activate Event | ✅ | ⭕️ manually | ❌ |
Deactivate Event | ✅ | ⭕️ manually | ❌ |
Demo
List of heroes
Table of heroes with table schema form
Editable Demo
Stackblitz
Github
Getting started
Step 1: Install @ngxd/core
:
NPM
npm install --save @ngxd/core
Yarn
yarn add @ngxd/core
Step 2: Import the NgxdModule:
import { NgxdModule } from '@ngxd/core';
@NgModule({
declarations: [ AppComponent ],
imports: [ BrowserModule, NgxdModule ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
Step 3: Create components that your want to use dynamically:
@Component({
selector: 'app-dynamic-comp-a',
template: `I'm Dynamic Component A. Hello, {{ name }}!`
})
export class CompAComponent {
@HostBinding('style.color') @Input() color: string;
@Input() name: string;
@Output() action: EventEmitter<any> = new EventEmitter<any>();
@HostListener('click', ['$event.target'])
onClick($event) {
this.action.emit($event);
}
}
@Component({
selector: 'app-dynamic-comp-b',
template: `I'm Dynamic Component B. Hello, {{ name }}!`
})
export class CompBComponent {
@HostBinding('style.color') @Input() color: string;
@Input() name: string;
@Output() action: EventEmitter<any> = new EventEmitter<any>();
@HostListener('click', ['$event.target'])
onClick($event) {
this.action.emit($event);
}
}
Step 4: Add components to declarations
and entryComponents
:
@NgModule({
...
declarations: [ ..., CompAComponent, CompBComponent ],
entryComponents: [ CompAComponent, CompBComponent ]
})
export class AppModule {}
Step 5: Create a host component with the same inputs/outputs:
@Component({
selector: 'app-items',
template: `
<ng-container *ngFor="let item of items">
<ng-container *ngxComponentOutlet="
item.component;
context: { name: item.name }
"></ng-container>
</ng-container>
`
})
export class ItemsComponent {
@Input() color: string;
@Input() items: { name: string; component: Type<any> }[];
@Output() action: EventEmitter<any> = new EventEmitter<any>();
}
Step 6: Add the component to declarations
:
@NgModule({
...
declarations: [ ..., ItemsComponent ],
...
})
export class AppModule {}
Step 7: Now show dynamic component in AppComponent:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-items [items]="items" (action)="onAction($event)" color="red"></app-items>
`
})
export class AppComponent {
items = [
{
name: 'Angular 5!',
component: CompAComponent
},
{
name: 'Angular 6!',
component: CompBComponent
}
];
onAction($event) {
console.log($event);
}
}
And you will have in AppModule:
import { NgxdModule } from '@ngxd/core';
@NgModule({
imports: [ BrowserModule, NgxdModule ],
declarations: [ AppComponent, CompAComponent, CompBComponent, ItemsComponent ],
entryComponents: [ CompAComponent, CompBComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
API
Input | Type | Default | Required | Description |
---|
[ngxComponentOutlet] | Type<any> | n/a | yes | |
[ngxComponentOutletContext] | any | n/a | no | |
[ngxComponentOutletInjector] | Injector | n/a | no | |
[ngxComponentOutletContent] | any[][] | n/a | no | |
[ngxComponentOutletNgModuleFactory] | NgModuleFactory<any> | n/a | no | |
Output | Type | Description |
---|
(ngxComponentOutletActivate) | any | |
(ngxComponentOutletDeactivate) | any | |
Advanced Use Cases
Here is a demo repository showing ngx-component-outlet and Angular in action.