如何在角度选项卡中加载动态组件?

Kri*_*nan 5 angular

我需要将组件以角度动态加载到选项卡中。我有一个父组件,里面有角标签。在选项卡控件中,我需要动态加载子组件。

最初,当标签被加载时,它应该加载一个 component1,并且在一些用户交互中,它应该触发事件,该事件将加载其他标签和其他子组件以加载到其中。

我的要求是在每个选项卡内动态加载任何子组件。

我在选项卡内动态加载子组件时遇到问题,不知道如何进一步处理?

我在stackblitz 中创建了一个用于演示的 POC

我的父组件如下:

    import {Component, ViewChild, AfterViewInit, TemplateRef, ComponentRef, ViewContainerRef} from '@angular/core';
    import { ComponentFactoryResolver } from '@angular/core';
    import { Component1 } from './Component1';
    import { Component2 } from './Component2';

    @Component({
      selector: 'home',
      template: `<mat-tab-group class="demo-tab-group">
   <mat-tab *ngFor="let tab of homepageTabs; let i = index" label="{{tab.label}}">

          <!--Component1 and Component2 to be loaded here... what is the correct container object which can hold dynamic components ? -->

          <ng-template #container>{{tab.templateRef}}</ng-template>

    </mat-tab>
</mat-tab-group>`
    })
    export class HomeComponent {
      homepageTabs: any;
      @ViewChild('container', { read: ViewContainerRef }) dynamicTabPlaceholder;

      constructor(private cfr: ComponentFactoryResolver)
      {

        //Need to instantiate the components Component1 & Component2 dynamically and load here into the homepageTabs List
        const factory = this.cfr.resolveComponentFactory(Component1);
        const componentRef = this.dynamicTabPlaceholder.createComponent(factory);

         this.homepageTabs = [
          {
            label: 'HomeLabel',
            //templateRef: Component1,//How to assign the component1 instance here?
            tabTitle: 'HomeTitle'
          },
          {
            label: 'App Details',
            //templateRef: Component2,
            tabTitle: 'App Details'
          }
        ];
      }
    }
Run Code Online (Sandbox Code Playgroud)

我的子组件如下所示,

import {Component} from '@angular/core';

@Component({
  selector: 'Component1',
  template: `Component1 Loaded

  <md-list>
  <md-list-item class="md-2-line" ng-repeat="item in workbookSheetsList">
    <md-checkbox ng-model="item.done"></md-checkbox>
    <div class="md-list-item-text">
      <h3>{{item.name}}</h3>
    </div>
  </md-list-item>
</md-list>
  `,
  //styleUrls: ['./tabs-template-label-example.css']
})
export class Component1 {

  workbookSheetsList = [{ "name": "TestReport" }, { "name": "SimpleReport" }, { "name": "Highlighting" }, { "name": "CalculatedColumns" }, { "name": "DateFormat" }, { "name": "KPIIndicator" }];

  constructor(){
  }
}
Run Code Online (Sandbox Code Playgroud)

运行应用程序时出现以下错误,这表明我无法获得正确的容器引用来创建/加载组件?

TypeError: Cannot read property 'createComponent' of undefined
    at new HomePageComponent (homepage.component.ts:76)
    at createClass (core.es5.js:10946)
    at createDirectiveInstance (core.es5.js:10764)
    at createViewNodes (core.es5.js:12205)
    at createRootView (core.es5.js:12100)
    at callWithDebugContext (core.es5.js:13486)
Run Code Online (Sandbox Code Playgroud)

我在这里感到震惊,不知道如何加载要在选项卡内加载的子组件:-

  1. 可以容纳放置在里面的动态组件的容器对象是什么?

    import {Component, ViewChild, AfterViewInit, TemplateRef, ComponentRef, ViewContainerRef} from '@angular/core';
    import { ComponentFactoryResolver } from '@angular/core';
    import { Component1 } from './Component1';
    import { Component2 } from './Component2';

    @Component({
      selector: 'home',
      template: `<mat-tab-group class="demo-tab-group">
   <mat-tab *ngFor="let tab of homepageTabs; let i = index" label="{{tab.label}}">

          <!--Component1 and Component2 to be loaded here... what is the correct container object which can hold dynamic components ? -->

          <ng-template #container>{{tab.templateRef}}</ng-template>

    </mat-tab>
</mat-tab-group>`
    })
    export class HomeComponent {
      homepageTabs: any;
      @ViewChild('container', { read: ViewContainerRef }) dynamicTabPlaceholder;

      constructor(private cfr: ComponentFactoryResolver)
      {

        //Need to instantiate the components Component1 & Component2 dynamically and load here into the homepageTabs List
        const factory = this.cfr.resolveComponentFactory(Component1);
        const componentRef = this.dynamicTabPlaceholder.createComponent(factory);

         this.homepageTabs = [
          {
            label: 'HomeLabel',
            //templateRef: Component1,//How to assign the component1 instance here?
            tabTitle: 'HomeTitle'
          },
          {
            label: 'App Details',
            //templateRef: Component2,
            tabTitle: 'App Details'
          }
        ];
      }
    }
Run Code Online (Sandbox Code Playgroud)

  1. 如何引用这个容器对象并将动态组件分配给它

import {Component} from '@angular/core';

@Component({
  selector: 'Component1',
  template: `Component1 Loaded

  <md-list>
  <md-list-item class="md-2-line" ng-repeat="item in workbookSheetsList">
    <md-checkbox ng-model="item.done"></md-checkbox>
    <div class="md-list-item-text">
      <h3>{{item.name}}</h3>
    </div>
  </md-list-item>
</md-list>
  `,
  //styleUrls: ['./tabs-template-label-example.css']
})
export class Component1 {

  workbookSheetsList = [{ "name": "TestReport" }, { "name": "SimpleReport" }, { "name": "Highlighting" }, { "name": "CalculatedColumns" }, { "name": "DateFormat" }, { "name": "KPIIndicator" }];

  constructor(){
  }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我解决这个问题并让我知道如何进一步进行?

https://stackblitz.com/edit/angular-e7fnhd?file=app%2Fhome.component.ts

pix*_*its 0

对于动态创建的任何组件,您需要将它们添加entryComponents到 ngModule 中。这是编译器在捆绑包中包含用于创建它们的工厂的提示。

@NgModule({
    declarations: [
       SomeDynamicComponent
    ],
    entryComponents: [
       SomeDynamicComponent
    ]
})
Run Code Online (Sandbox Code Playgroud)