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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With