angular2 ng-template in a separate file

前端 未结 5 914
孤城傲影
孤城傲影 2021-02-19 09:05

angular2 how to use ng-template from a different file? When I place the ng-template within the same HTML where I use it works but when I move ng-template into a separate file th

5条回答
  •  [愿得一人]
    2021-02-19 09:46

    Expanding on the answer by @peter554 for reasons of explanation and portability. This will let you use a template across components.

    To use:

    'app.module.ts'
    
    import {NgModule} from '@angular/core';
    import {
        IdcPortalDirective, IdcTemplatePortalDirective,
        PortalService
    } from './idc-template-portal/idc-template-portal.component';
    
    @NgModule({
        declarations: [
            IdcPortalDirective,
            IdcTemplatePortalDirective
        ],
        imports: [],
        exports: [],
        providers: [
            PortalService
        ],
        bootstrap: [AppComponent]
    })
    export class AppModule {}
    
    './idc-template-portal/idc-template-portal.component.ts'
    
    import {
        AfterViewInit,
        Directive,
        Injectable,
        Input,
        OnInit, Output,
        TemplateRef,
        ViewContainerRef
    } from '@angular/core';
    /*** Input Template ***/
    /*** Template Contents ***/
    @Directive({
        selector: '[idcPortal]'
    })
    export class IdcPortalDirective implements OnInit {
        @Input() outlet: string;
        @Output() inlet: string = this.outlet;
    
        constructor(private portalService: PortalService, public templateRef: TemplateRef) {}
    
        ngOnInit():void {
            this.portalService.registerInlet(this);
        }
    
    }
    /*** Output Container ***/
    /***  ***/
    @Directive({
        selector: '[idcPortalOutlet]'
    })
    export class IdcTemplatePortalDirective implements OnInit, AfterViewInit {
        @Input() appPortalOutlet: string;
        @Output() outlet: string = this.appPortalOutlet;
    
        constructor(private portalService: PortalService, public viewContainerRef: ViewContainerRef) {}
    
        ngOnInit():void {
            this.portalService.registerOutlet(this);
        }
    
        ngAfterViewInit() {
            this.portalService.initializePortal(this.appPortalOutlet);
        }
    
    }
    @Injectable({
        providedIn: 'root'
    })
    export class PortalService {
        outlets = new Map();
        inlets = new Map();
    
        registerOutlet(outlet: IdcTemplatePortalDirective) {
            this.outlets[outlet.outlet] = outlet;
        }
    
        registerInlet(inlet: IdcPortalDirective) {
            this.inlets[inlet.inlet] = inlet;
        }
    
        initializePortal(portal:string) {
            const inlet: IdcPortalDirective = this.inlets[portal];
            const outlet: IdcTemplatePortalDirective = this.outlets[portal];
            outlet.viewContainerRef.clear();
            outlet.viewContainerRef.createEmbeddedView(inlet.templateRef);
        }
    }
    

    He,@peter554, mentions reinventing the wheel in regards to the Angular CDK portals package. However, I find his/this implementation to make more sense in the way it's used in the application flow and the ease in which a template can be ported from component to another component that contains the portal outlet (allowing component to component->portal template communication. For example within a component template implementing the Angular Material MatBottomSheet (idcBottomSheet)).

    The 'input' element:

    
    
    
    
    
        
    A place for your thoughts:

    The 'output' element (inside your MatBottomSheet component template):

    
    

提交回复
热议问题