angularprimengwebpack-3typescript-2.5

While clicking on tab i need to load particular component in angular2


I am trying to load components in tab. while clicking on particular tab i need to load the particular component.But it's loading all component while navigating to that component.

.html

<p-tabView orientation="left" (onChange)="onTabChange($event)">
       <p-tabPanel *ngFor="let item of items" style="border: solid 1px; padding: 20px;margin: 20px;" [selected]="activeTabIndex==i">
              <strong> When you click here, 
              I should load the <span style="color:red"> {{item.name}} </span>
              component below</strong> <br />

              <ng-container *ngComponentOutlet="childmap[item.name] "></ng-container>

          <br />
        </p-tabPanel>
</p-tabView>

.ts

@Component({
  selector: 'my-app',
  templateUrl:'dashboard.html' 
  `
})
export class App {
 activeTabIndex: number = 0;

childmap = {
        'slider': sliderComponent,
        'user': usersComponent,
        'alert danger': AlertDangerComponent
         }


items:Array<any> = [
    {
      name: 'slider' 
    },
    {
      name: 'user'
    },
    {
      name: 'alert danger'
    }

      ]
 onTabChange(event: any) {
        this.activeTabIndex = event.index;
    }
  }

Solution

  • There are many solution for this kind of things. Please What I have done by using ngComponentOutlet.

    Here is the tab-container:

    import {Component, Input} from '@angular/core'
    import {TabContentAlternativeComponent} from './tab-content-alternative.component'
    import {BasicContent} from './basic-content'
    
    @Component({
      selector: 'tab',
      template: ''
    })
    export class TabComponent {
      @Input() title: string;
      @Input() contentRef: BasicContent;
      active = false;
    }
    

    This is a very simple component which knows its own tab name, an active state and the body component reference which should be loaded when somebody selects the tab.

    Then we create several body components which will be loaded dynamically:

    export class BasicContent {
    
    }
    

    Component 1

      import {Component, Input, OnInit} from '@angular/core'
    import {BasicContent} from './basic-content'
    
    @Component({
      selector: 'tab-content',
      template: `
          <p>Hey</p>
      `,
    })
    export class TabContentComponent extends BasicContent {
    }
    

    Component 2

       import {Component, Input} from '@angular/core'
    import {BasicContent} from './basic-content'
    
    @Component({
      selector: 'tab-content-alternative',
      template: `
          <p>Hey, this is an alternative content</p>
      `,
    })
    export class TabContentAlternativeComponent extends BasicContent {
    }
    

    Here is the tabs-container component with tabs rendering and an empty placeholder for dynamic body components:

        import {AfterContentInit, Component, ContentChildren, QueryList} from '@angular/core'
    import {TabComponent} from './tab.component'
    import {BasicContent} from 'basic-content'
    
    import 'rxjs/Rx';
    import {Observable, BehaviorSubject} from 'rxjs/Rx';
    
    @Component({
      selector: 'tab-container',
      template: `
        <div class="tab-header">
          <div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">{{tab.title}}</div>
        </div>
    
        <div class="tab-content">
          <ng-container *ngComponentOutlet="content | async"></ng-container>
        </div>
      `,
    })
    export class TabContainerComponent implements AfterContentInit {
      @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
    
      private contentSbj = new BehaviorSubject<BasicContent>(null);
      content = this.contentSbj.asObservable();
    
      ngAfterContentInit() {
        const activeTabs = this.tabs.filter((tab) => tab.active);
        if (activeTabs.length === 0) {
          this.selectTab(this.tabs.first);
        }
      }
    
      selectTab(tab: TabComponent) {
        this.tabs.toArray().forEach(tab => tab.active = false);
        tab.active = true;
        this.contentSbj.next(tab.contentRef);
      }
    }
    

    TitleMapping

    import {TabContentComponent} from './tab-content.component';
    import {TabContentAlternativeComponent} from './tab-content-alternative.component';
    
    interface TitleMapping {
      title: string;
      contentComponent: BasicContent;
    }
    
    export const allTabs: TitleMapping[] = [
      {title: "Tab 1", contentComponent: TabContentComponent},
      {title: "Tab 2", contentComponent: TabContentAlternativeComponent},
      {title: "Tab 3", contentComponent: TabContentComponent}
    ]
    

    And this is how it can be used in some parent component:

    import {TabContentComponent} from './tab/tab-content.component'
    import {TabContentAlternativeComponent} from './tab/tab-content-alternative.component'
    
    @Component({
      selector: 'my-app',
      template: `
        <tab-container>
          <tab title="Tab 1" [contentRef]="normalContent"></tab>
          <tab title="Tab 2" [contentRef]="alternativeContent"></tab>
        </tab-container>
      `,
    })
    export class App {
      normalContent = TabContentComponent;
      alternativeContent = TabContentAlternativeComponent;
    }
    

    Here is working Plunkr

    I have used this with my projects and working fine as your requirement.