Raúl Jiménez

elecash@gmail.com

@elecash

CREANDO CONTENIDO DINÁMICO CON ANGULAR

sobre mí

Angular GDE

videogular

academy partner

toptal partner

component factory resolver

crear objeto

@Component({
    selector: 'app-cfr-demo',
    templateUrl: './cfr-demo.component.html',
    styleUrls: [ './cfr-demo.component.scss' ],
    encapsulation: ViewEncapsulation.None
})
export class CfrDemoComponent {
    @ViewChild('placeholder', { read: ViewContainerRef }) viewContainerRef;

    constructor(private componentFactoryResolver: ComponentFactoryResolver) {}

    addItem(type: string) {
        const clazz = ViewOneComponent;
        const factory = this.componentFactoryResolver.resolveComponentFactory(clazz);
        const component = this.viewContainerRef.createComponent(factory);
    }
}

Con component factory resolver podemos crear componentes al vuelo

en nuestro template

<button (click)="addItem('one')">Add View One</button>
<button (click)="addItem('two')">Add View Two</button>

<ng-template #placeholder></ng-template>

Añadimos el ng-template donde instanciar el objeto creado dinámicamente

pasar parámetros

@Component({
    selector: 'app-cfr-demo',
    templateUrl: './cfr-demo.component.html',
    styleUrls: [ './cfr-demo.component.scss' ],
    encapsulation: ViewEncapsulation.None
})
export class CfrDemoComponent {
    @ViewChild('placeholder', { read: ViewContainerRef }) viewContainerRef;

    constructor(private componentFactoryResolver: ComponentFactoryResolver) {}

    addItem(type: string) {
        const clazz = ViewOneComponent;
        const factory = this.componentFactoryResolver.resolveComponentFactory(clazz);
        const component = this.viewContainerRef.createComponent(factory);
        (component.instance as IView).customMessage = 'my custom message';
    }
}

También podemos pasar parámetros y modificar propiedades de nuestro objeto

demo

template outlet

Con template outlet podemos modificar templates internos de otro componente

<app-custom-list [items]="items">
    <ng-template let-item="item">
        <h2 class="red">{{ item.title }}</h2>
        <strong>{{ item.speaker }}</strong>
    </ng-template>
</app-custom-list>

componente hijo

En nuestro componente hijo recogemos la referencia del template en el padre con TemplateRef

@Component({
    selector: 'app-custom-list',
    templateUrl: './custom-list.component.html',
    styleUrls: [ './custom-list.component.scss' ],
    encapsulation: ViewEncapsulation.None
})
export class CustomListComponent {
    @Input() items: Array<IItem> = [];

    @ContentChild(TemplateRef) renderer;

    constructor() {}
}

componente hijo

Y ya podemos instanciar ese template en el hijo conservando las referencias con ngTemplateOutletContext

<ul>
    <li *ngFor="let item of items">
        <ng-template [ngTemplateOutlet]="renderer" 
                     [ngTemplateOutletContext]="{item: item}">
        </ng-template>
    </li>
</ul>

demo

¡gracias!