I display several tabs with a loop ngFor using Angular Material tabs. This works properly however now I would like to open the second tab when initialised and not the first tab. Therefore, I add the property selectedIndex in the mat-tab-group but it doesn't work and still continues to open on the first tab.
HTML
<mat-tab-group class="col-10 offset-1" (selectedTabChange)="onTabChanged($event)" [selectedIndex]="1">
<mat-tab label={{tab.name}} *ngFor="let tab of tabs; let index = index">
<div>
Values: {{tab.values}}
</div>
</mat-tab>
</mat-tab-group>
The variable "tabs" is fetched with a service from the server in ngOnInit like this:
COMPONENT
this.api.getDataset(this.route.snapshot.params["experimentid"]).subscribe(
res => {
this.tabs = res;
},
err => {
console.log(err);
}
);
I think it comes from here because if I set the tabs manually without requesting to the server it works. Like this:
this.tabs = [{name: "X2", values: "52"}, {name: "Z2", values: "52"}, {name: "R2", values: "52"}]
<mat-tab-group>
only reads the [selectedIndex]
input when the component is first created. Afterwards the output binding (selectedIndex)
lets you track tab changes.
I think you're setting the value 1
before that tab exists.
The problem is that *ngFor
is creating the children mat-tab
components afterwards. When <mat-tab-group>
is notified that the children have changed it defaults to the first tab.
The only work-around that I know of is to trigger a change to the [selectedIndex]
binding after the child <mat-tab>
components have been created.
Update your component to have a property:
public selectedIndex: number = 0;
Use this as the binding for the selectedIndex input:
<mat-tab-group class="col-10 offset-1"
(selectedTabChange)="onTabChanged($event)"
[selectedIndex]="selectedIndex">
Inject these dependencies into your component:
public constructor(private change: ChangeDetectorRef) {}
Update your subscribe to change the selected index after the *ngFor
has finished updating the document.
this.api.getDataset(this.route.snapshot.params["experimentid"]).subscribe(res => {
this.tabs = res;
// wait for ngFor to finish
window.setTimeout(()=>{
this.selectedIndex = 1;
this.change.markForCheck();
});
});
You can set the selectedIndex
after your service data is available. You need to do below changes:
Get hold of a reference to MatTabGroup
instance in your component (the component whose template contains mat-tab-group
) by declaring below attribute:
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
Then set the selectedIndex in subscribe
method call while updating new value for tabs
.subscribe(
res => {
this.tabs = res;
this.tabGroup.selectedIndex = 1;
},
Overall, you component may look somewhat like below:
import {Component, OnInit, ViewChild } from '@angular/core';
import { MatTabGroup } from '@angular/material';
@Component({
selector: 'tab-group-basic-example',
templateUrl: 'tab-group-basic-example.html',
styleUrls: ['tab-group-basic-example.css'],
})
export class TabGroupBasicExample implements OnInit {
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
tabs = [];
ngOnInit() {
this.api.getDataset(experimentId).subscribe(
res => {
this.tabs = res;
this.tabGroup.selectedIndex = 1;
},
err => {
console.log(err);
}
);
}
}
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