angular 4+ assign @Input for ngComponentOutlet dynamically created component

前端 未结 3 1743
渐次进展
渐次进展 2020-11-30 05:54

In Angular 4 to dynamically create a component you can use ngComponentOutlet directive: https://angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-dir

相关标签:
3条回答
  • 2020-11-30 06:37

    I think for now you can use

    https://www.npmjs.com/package/ng-dynamic-component

    It is made specifically for this issue

    0 讨论(0)
  • 2020-11-30 06:39

    With the help of the post of @Günter Zöchbauer I solved a similar problem this way - I hope you can adapt it somehow.

    First I defined some interfaces:

    // all dynamically loaded components should implement this guy
    export interface IDynamicComponent { Context: object; }
    
    // data from parent to dynLoadedComponent
    export interface IDynamicComponentData {
      component: any;
      context?: object;
      caller?: any;
    }
    

    then I implemented them inside of the dynamically loaded component

    dynamicLoadedComponentA.ts

    // ...
    export class DynamicLoadedComponentA implements IDynamicComponent {
    // ...
    
    // data from parent
    public Context: object;
    
    // ...
    

    After that I built a new component which is responsible for the magic. Important here is that I had to register all dyn. loaded components as entryComponents.

    dynamic.component.ts

    @Component({
      selector: 'ngc-dynamic-component',
      template: ´<ng-template #dynamicContainer></ng-template>´,
      entryComponents: [ DynamicLoadedComponentA ]
    })
    export class DynamicComponent implements OnInit, OnDestroy, OnChanges {
      @ViewChild('dynamicContainer', { read: ViewContainerRef }) public dynamicContainer: ViewContainerRef;
    
      @Input() public componentData: IDynamicComponentData;
    
      private componentRef: ComponentRef<any>;
      private componentInstance: IDynamicComponent;
    
      constructor(private resolver: ComponentFactoryResolver) { }
    
      public ngOnInit() {
        this.createComponent();
      }
    
      public ngOnChanges(changes: SimpleChanges) {
        if (changes['componentData']) {
          this.createComponent();
        }
      }
    
      public ngOnDestroy() {
        if (this.componentInstance) {
          this.componentInstance = null;
        }
        if (this.componentRef) {
          this.componentRef.destroy();
        }
      }
    
      private createComponent() {
        this.dynamicContainer.clear();
        if (this.componentData && this.componentData.component) {
          const factory: ComponentFactory<any> = this.resolver.resolveComponentFactory(this.componentData.component);
          this.componentRef = this.dynamicContainer.createComponent(factory);
          this.componentInstance = this.componentRef.instance as IDynamicComponent;
    
          // fill context data
          Object.assign(this.componentInstance.Context, this.componentData.context || {});
    
          // register output events
          // this.componentRef.instance.outputTrigger.subscribe(event => console.log(event));
        }
      }
    }
    

    here the usage of this shiny new stuff:

    app.html

    <!-- [...] -->
    <div>
      <ngc-dynamic-component [componentData]="_settingsData"></ngc-dynamic-component>
    </div>
    <!-- [...] -->
    

    app.ts

    // ...
      private _settingsData: IDynamicComponent = {
        component: DynamicLoadedComponentA,
        context: { SomeValue: 42 },
        caller: this
      };
    // ...
    
    0 讨论(0)
  • 2020-11-30 06:48

    Such a feature was discussed in the pull request for ngComponentOutlet but was dropped for now. Even the componentRef shown currently in https://angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-directive.html is not public and therefore not available https://github.com/angular/angular/blob/3ef73c2b1945340ca6bd21f1790260c88698ae26/modules/%40angular/common/src/directives/ng_component_outlet.ts#L78

    I'd suggest you create your own directive derived from https://github.com/angular/angular/blob/3ef73c2b1945340ca6bd21f1790260c88698ae26/modules/%40angular/common/src/directives/ng_component_outlet.ts#L72

    and assign values to inputs like shown in Angular 2 dynamic tabs with user-click chosen components

    this.compRef.instance.someProperty = 'someValue';
    
    0 讨论(0)
提交回复
热议问题