2017年1月1日 星期日

[ASP.NET Core X Angular] (13) - Dynamically load Component (2)

 Angular    Dynamic Component     ComponentFactoryResolver   


Introduction


We will update our Component-Outlet directive and make it support passing parameter to the component.


Related articles


Environment

Angular 2.1.0



Implement


Update Component Outlet

Add a new input property: inputValue, to the ComponentOutlet.

component-oulet.directive.ts

import {  Directive, Component, ComponentFactory, OnChanges, Input, ViewContainerRef, Compiler, ComponentFactoryResolver } from '@angular/core';

@Directive({
    selector: '[component-outlet]'
})
export class ComponentOutlet implements OnChanges {
    @Input() selector: string;
    @Input() inputValue: any;

    componentRef;

    constructor(
        private vcRef: ViewContainerRef,
        private resolver: ComponentFactoryResolver) {
    }

    ngOnChanges() {

        if (!this.selector) return;

        const factories = Array.from(this.resolver['_factories'].values());
        const factory: any = factories.find((x: any) => x.selector === this.selector);
        const compRef:any = this.vcRef.createComponent(factory);

        //Set input value for the component (optional)
        compRef.instance.inputValue = this.inputValue;

        if (this.componentRef) {
            this.componentRef.destroy();
        }

        this.componentRef = compRef;
    }

    public ngOnDestroy() {
        if (this.componentRef) {
            this.componentRef.destroy();
            this.componentRef = null;
        }
    }
}




Usage

Let’s update the previous sample that users can choose the style for showing the customers’ data and HOW MANY records should be displayed.

app.component.ts

<!-- New -->
<div class="col-sm-3"><input type="text" class="form-control" [(ngModel)]="maxDisplayNum" value="" /></div>

<!-- Update -->
<div component-outlet [selector]="component" [inputValue]="maxDisplayNum"></div>



Okay, we can pass a parameter to the Component-Outlet and it’s time to update the target components.

Take “List style” component for example,

list.component.ts

import {Component, OnInit, Input} from '@angular/core';
import {Customer} from '../../../class/Customer';
import {CustomerService} from '../../../service/customer.service';
import {RestUriService} from '../../../service/resturi.service';


@Component({
    selector: 'customerdynamic-list',
    providers: [CustomerService, RestUriService],
    templateUrl: '/app/component/Basic/CustomerDynamic/list.component.html'
})

export class CustomerDynamicListComponent implements OnInit {
    @Input() inputValue: number;

    customers: Customer[];
    constructor(private custService: CustomerService) {
    }


    ngOnInit() {
        this.initCustomers();
    }

    private initCustomers() {
        this.custService.getAll().then(
            data => {
                this.customers = [];
                if (!this.inputValue) {
                    this.customers = data
                }
                else {
                    for (let i = 0; i < this.inputValue; i++) {
                        this.customers.push(data[i]);
                    }
                }
            });
    }
}




Demo
























Github





Reference






沒有留言:

張貼留言