Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load a dynamic component in angular tab?

Tags:

angular

I need to load the components dynamically into the tabs in angular. I have a parent component which has angular tabs in it. Inside the tab control, I need to load the child components dynamically.

Initially when the Tabs are loaded it should be loaded with a component1, and on some user interactions it should trigger the event which would load additional tabs and other child components to be loaded inside it.

My requirement is load any child components dynamically inside the each tabs.

I am facing issues in loading the child components dynamically inside the tab and not understanding how to proceed further?

I have created a POC for demo in stackblitz

My Parent component is as follows:

    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'
          }
        ];
      }
    }

My child component looks like below,

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(){
  }
}

I am getting the below error when I run the application, which indicates that I am not able to get the correct container reference to create/load the component?

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)

I am struck here and not sure how to load the child components to be loaded inside a tab :-

  1. what would be the container object which can hold the dynamic components placed inside

<mat-tab-group class="demo-tab-group">
       <mat-tab *ngFor="let tab of homepageTabs; let i = index" label="{{tab.label}}">
            <div class="demo-tab-content">
              <!--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>
            </div>
        </mat-tab>
    </mat-tab-group>
  1. how to reference this container object and assign the dynamic components into it

    {
      label: 'HomeLabel',
      //templateRef: Component1,//How to assign the component1 instance here?
      tabTitle: 'HomeTitle'
    },

Can anybody help me with this issue and let me know how to proceed further?

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

like image 809
Krishnan Avatar asked Nov 08 '22 13:11

Krishnan


1 Answers

I think the answer here is to use the angular router functionality to load the dynamic content you are referring to.

The key thing is that I learned the hard way is to NOT make the main component of the application a route. So do not place the router-outlet in the index.html file but as an element of the app-component.

Check out my stackblitz for a demo

This way you are also able to build a static layout for you application that remains the same on the inner content changes.

like image 108
Cliff Crerar Avatar answered Nov 14 '22 22:11

Cliff Crerar