美文网首页angular
Dynamic Create Angular Views

Dynamic Create Angular Views

作者: forks1990 | 来源:发表于2018-09-20 15:53 被阅读1次

    There are two kinds of view in angular: embedded view and host view.

    Embedded View

    Embedded view create from a template, can not directly operate on template, but template ref instead.

    First define template using ng-template tag embedded in component template string or file:

    @Component({
        selector: 'sample',
        template: `
            <ng-template #tpl>
                <span>I am span in template</span>
            </ng-template>
        `
    })
    

    Then get template ref:

    export class SampleComponent implements AfterViewInit {
        @ViewChild("tpl") tpl: TemplateRef<any>;
    

    Create:

    
        ngAfterViewInit() {
            let elementRef = this.tpl.elementRef;
            // outputs `template bindings={}`
            console.log(elementRef.nativeElement.textContent);
        }
    }
    

    Put them together:

    @Component({
        selector: 'sample',
        template: `
            <ng-template #tpl>
                <span>I am span in template</span>
            </ng-template>
        `
    })
    export class SampleComponent implements AfterViewInit {
        @ViewChild("tpl") tpl: TemplateRef<any>;
    
        ngAfterViewInit() {
            let elementRef = this.tpl.elementRef;
            // outputs `template bindings={}`
            console.log(elementRef.nativeElement.textContent);
        }
    }
    

    Host view

    Only entry component can dynamically created, because component may use DI, an instance of Injector needed to do the DI job. Fortunately each component instance bound with an injector, we can get it from ID system.

    Here is the sample code:

    constructor(private injector: Injector,
                private r: ComponentFactoryResolver) {
        // resolves component factory, btw factory is generated by angular
        // compiler for each our component.
        let factory = this.r.resolveComponentFactory(ColorComponent);
        // create component view, and returns newly created ref of the 
        // component.
        let componentRef = factory.create(injector);
        // get the hosted view.
        let view = componentRef.hostView;
    }
    

    Add view to UI

    A view itself is useless if not add to component tree, we need view container.

    View container is defined using a special tag ng-container like:

            <span>I am first span</span>
            <ng-container #vc></ng-container>
            <span>I am last span</span>
    

    At runtime, <ng-container> rendered as html comment, it is nothing more than a placeholder.

    Again, we can not get ViewContainer but ViewContainerRef:

    export class SampleComponent implements AfterViewInit {
        @ViewChild("vc", {read: ViewContainerRef}) vc: ViewContainerRef;
    
    

    Using ViewContainer operate on views:

    class ViewContainerRef {
        ...
        clear() : void
        insert(viewRef: ViewRef, index?: number) : ViewRef
        get(index: number) : ViewRef
        indexOf(viewRef: ViewRef) : number
        detach(index?: number) : ViewRef
        move(viewRef: ViewRef, currentIndex: number) : ViewRef
    }
    

    As you can see, not just insert views at the placeholder, but do almost anything. Now back to business, insert our dynamic created views:

    @Component({
        selector: 'sample',
        template: `
            <span>I am first span</span>
            <ng-container #vc></ng-container>
            <span>I am last span</span>
            <ng-template #tpl>
                <span>I am span in template</span>
            </ng-template>
        `
    })
    export class SampleComponent implements AfterViewInit {
        @ViewChild("vc", {read: ViewContainerRef}) vc: ViewContainerRef;
        @ViewChild("tpl") tpl: TemplateRef<any>;
    
        ngAfterViewInit() {
            let view = this.tpl.createEmbeddedView(null);
            this.vc.insert(view);
        }
    }
    

    Note: to get ViewContaierRef through @ViewChild, must provide {read: ViewContainerRef} argument, because <ng-container> element itself is not ViewContainer.

    To remove view from ViewContainer, call .detach() method.

    ViewContainer defines convenient methods to create views:

    class ViewContainerRef {
        createComponent(componentFactory...): ComponentRef<C>;
        createEmbeddedView(templateRef...): EmbeddedViewRef<C>;
    }
    

    相关文章

      网友评论

        本文标题:Dynamic Create Angular Views

        本文链接:https://www.haomeiwen.com/subject/ltqnnftx.html