Best way to quickly use Dynamic Components with Angular
NGX Dynamic v7 will arriving soon! While this is a major version change (from 0.x to 7.x).
Use like NgComponentOutlet
but with @Input/@Output
auto bindings:
<ng-container *ngxComponentOutlet="component"></ng-container>
There are several modes of operation of the directive.
A simple variant of binding through the parent component.
@Component({
template: `
<ng-container
*ngxComponentOutlet="component"
></ng-container>
`
})
class DynamicComponent {
@Input() entity;
@Output() action;
}
Additionally there is autobinding through the context. This is useful when you need to display something through *ngFor. Context has a higher priority than the inputs in the component.
<ng-container *ngFor=“let color of colors”
<ng-container
*ngxComponentOutlet="
component;
context: { color: color }
"></ng-container>
</ng-container>
For ease of selecting the required component, there is ResolvePipe, which expects NgxdResolver to enter, and returns the required component.
<ng-container
*ngxComponentOutlet="
resolver | resolve: entity
"></ng-container>
Through the host component, when the inputs and outputs are initialized explicitly. This option is difficult to use and deprecated.
<!-- host component -->
<app-dynamic
<!-- dynamic component -->
[ngxComponentOutlet]="component"
<!-- regular input -->
[entity]="entity"
<!-- regular output -->
(action)="onAction($event)">
</app-dynamic>
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 | ❌ |
List of heroes
Table of heroes with table schema form
npm install --save @ngxd/core
yarn add @ngxd/core
import { NgxdModule } from '@ngxd/core';
@NgModule({
declarations: [ AppComponent ],
imports: [ BrowserModule, NgxdModule ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
@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);
}
}
@NgModule({
...
declarations: [ ..., CompAComponent, CompBComponent ],
entryComponents: [ CompAComponent, CompBComponent ]
})
export class AppModule {}
@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>();
}
@NgModule({
...
declarations: [ ..., ItemsComponent ],
...
})
export class AppModule {}
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);
}
}
import { NgxdModule } from '@ngxd/core';
@NgModule({
imports: [ BrowserModule, NgxdModule ],
declarations: [ AppComponent, CompAComponent, CompBComponent, ItemsComponent ],
entryComponents: [ CompAComponent, CompBComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
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 |
Here is a demo repository showing NGX Dynamic and Angular in action.