5

I'm trying to create a wrapper around MatTabs that exposes all the properties of the MatTabs and Came across this question : Angular Material Tabs not working with wrapper component . I added other tabs properties and events to it. The events seems to be triggering properly.

The problem comes when I add a new tab.The array is getting updated but the UI remains same.

HTML

<div>
  <span class="example-input-label"> Selected tab index: </span>
  <mat-form-field>
    <input matInput type="number" [formControl]="selected">
  </mat-form-field>
</div>

<div>
  <button mat-raised-button
          class="example-add-tab-button"
          (click)="addTab(selectAfterAdding.checked)">
    ADD NEW TAB
    <br/>
  </button>
  <mat-checkbox #selectAfterAdding> Select tab after adding </mat-checkbox>
</div>

<custom-tabs [selectedIndex]="selected.value"
               (sqSelectedIndexChange)="selected.setValue($event)">
  <custom-tab *ngFor="let tab of tabs; let index = index" [label]="tab">
    Contents for {{tab}} tab
    <button mat-raised-button
            class="example-delete-tab-button"
            [disabled]="tabs.length === 1"
            (click)="removeTab(index)">
      Delete Tab
      <br/>

    </button>
  </custom-tab>
</custom-tabs>

TS

tabs = ['First', 'Second', 'Third'];
  selected = new FormControl(0);

  addTab(selectAfterAdding: boolean) {
    this.tabs.push('New');
    console.log(this.tabs);
    if (selectAfterAdding) {
      this.selected.setValue(this.tabs.length - 1);
    }
  }

  removeTab(index: number) {
    this.tabs.splice(index, 1);
  }

Custom Tabs StackBlitz.

MatTabs Stackblitz

Ideally I'm looking to expose all the features that MatTabs provides out of the box and then some.

kal93
  • 522
  • 1
  • 9
  • 22

1 Answers1

1

So, the reason why the tabs aren't loading is because of the code in the custom-tabs component's ngViewAfterInit() function. It was initialized, but that's it. So the this.tabGroup never gets updated with the current tabs and thus wasn't being reflected in the UI. So I added a subscription to watch for when the tabs change, and use the same logic (which I am not sure is 100% correct, but it gets the job done).

  public ngAfterViewInit() {
    const matTabsFromQueryList = this.tabs.map((tab) => tab.matTab);
    const list = new QueryList<MatTab>();
    list.reset([matTabsFromQueryList]);
    this.tabGroup._tabs = list;
    this.tabGroup.ngAfterContentInit();

   // watches for when the tabs change
    this.tabs.changes.subscribe(value => {
      const matTabsFromQueryList = value.map((tab) => tab.matTab);
      const list = new QueryList<MatTab>();
      list.reset([matTabsFromQueryList]);
      this.tabGroup._tabs = list;
      this.tabGroup.ngAfterContentInit();
      });
  }

This (again) isn't the most elegant solution because you need to interact with the tabs before they load, but it preserves the context (as demonstrated by the input box). The tabs wouldn't update without selecting a different tab, so I had to do a hacky solution where I switch this.selected.value to -1 then switch back to the correct tab, so it's a little ugly but at least it works.

stackblitz

rhavelka
  • 2,283
  • 3
  • 22
  • 36
  • Thanks. I've multiple tabs which contains table with certain filter states in their views so this doesn't seem feasible.This issue is not present in the mat-tabs though.The wrapper seems to causing some change Detection issue. – kal93 Sep 04 '18 at 16:07
  • Reloading the DOM might cause some other issues in there. – kal93 Sep 04 '18 at 16:38
  • 1
    ah ok, well I am playing with some stuff so the stackblitz is going to be broken. yeah now that I look at your custom components a little closer it does seem to be a change detection issue. – rhavelka Sep 04 '18 at 16:39
  • 1
    I will have to come back to this later. But from what I can see (in the current stackblitz link), the component is getting created and the ts recognizes it. but for some reason the dom isn't loading it. – rhavelka Sep 04 '18 at 17:02
  • 1
    @kal93 I updated the answer and fiddle. play around with it and let me know if there is anything wrong that you need help with. (the top tabs is the vanilla way, the bottom tabs is your custom way) – rhavelka Sep 04 '18 at 19:38
  • Yes it did. Thank you for the all the help. – kal93 Sep 11 '18 at 18:03