简体   繁体   中英

Angular material tabs using ngComponentOutlet

I am using Angular Material Tabs to navigate different sections of a document. I've defined each tab in a TabItem class which looks like this:

class TabItem {
     constructor(
         public component: Type<any>, 
         public data: TabData,
         public active: boolean
     ) {}
}

In the view, I loop through each TabItem and use *ngComponentOutlet to render the component of each TabItem.

<mat-tab-group>
    <ng-container *ngFor="let tab of tabs">
        <mat-tab>
             <ng-template mat-tab-label>
                   <div class="mat-label-text" (click)="setActiveTab(tab)">{{ tab.data.label }}</div>
             </ng-template>

             <ng-container *ngComponentOutlet="tab.component"></ng-container>
        </mat-tab>
    </ng-container>
</mat-tab-group>

Everything works well... except I need access to the current TabItem in each of the resolved components to access its id, label, etc. The reason I am having trouble is because the examples online only show how to use ngComponentOutlet as a dynamic component. My components arent dynamic though... they are fixed, but created on the fly.

I dont know how I can use an injector since I am in a for loop... unless I create an injector for each individual item. I also dont want to subscribe to a service in every component... thats just ridiculous.

Here is a stackblitz of what I am trying to accomplish.

You can create a directive that will port desired data to your components:

data-provider.directive.ts

import { Directive, Input } from "@angular/core";

@Directive({
  selector: '[dataProvider]'
})
export class DataProviderDirective {
  @Input('dataProvider') data: any;
}

tabs.html

<ng-container *ngFor="let tab of tabs">
  <mat-tab [dataProvider]="tab">

Now your dynamically generated component can read data from that directive:

tab-one.component.ts

import { Component, OnInit } from '@angular/core';
import { DataProviderDirective } from './data-provider.directive';

@Component({
  selector: 'app-tab-one',
  template: `
    <p>I am tab one!</p>
    <p>How can I access my respective TabItem?</p>
    <pre>{{ dataProvider.data | json }}</pre> 
  `,
})
export class TabOneComponent implements OnInit {

  constructor(public dataProvider: DataProviderDirective) { }

  ngOnInit() {
    console.log(this.dataProvider.data)
  }
}

Forked Stackblitz

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM