Материал mat-tab angular6 selectedIndex не работает с * ngFor

Я отображаю несколько вкладок с циклом ngFor, используя вкладки Angular Material. Это работает правильно, однако теперь я хотел бы открыть вторую вкладку при инициализации, а не первую вкладку. Поэтому я добавляю свойство selectedIndex в группу mat-tab-group, но оно не работает и продолжает открываться на первой вкладке.

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>

Переменная "tabs" извлекается службой с сервера в ngOnInit следующим образом:

КОМПОНЕНТ

this.api.getDataset(this.route.snapshot.params["experimentid"]).subscribe(
  res => {
    this.tabs = res;
  },
  err => {
    console.log(err);
  }
);

Я думаю, что это происходит отсюда, потому что, если я устанавливаю вкладки вручную, не запрашивая сервер, он работает. Нравится:

this.tabs = [{name: "X2", values: "52"}, {name: "Z2", values: "52"}, {name: "R2", values: "52"}]

person PierBJX    schedule 14.07.2018    source источник
comment
Попробуйте добавить *ngIf="tabs && tabs.length" в свой mat-tab-group компонент. См. Также пример ng-run.com/edit/OxHxsmOQUgfxuH0grSra.   -  person yurzui    schedule 14.07.2018
comment
@yurzui гораздо лучшее решение, чем мое. Это может не сработать, если изменить массив вкладок с одного набора на другой.   -  person Reactgular    schedule 14.07.2018


Ответы (2)


Вы можете установить selectedIndex после того, как ваши служебные данные станут доступны. Вам необходимо внести следующие изменения:

  1. Получите ссылку на экземпляр MatTabGroup в вашем компоненте (компонент, шаблон которого содержит mat-tab-group), объявив атрибут ниже:

    @ViewChild(MatTabGroup) tabGroup: MatTabGroup;
    
  2. Затем установите selectedIndex в вызове метода subscribe при обновлении нового значения для tabs

    .subscribe(
      res => {
        this.tabs = res;
        this.tabGroup.selectedIndex = 1;
      },
    

В целом ваш компонент может выглядеть примерно так:

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);
      }
    );
  }
}
person Wand Maker    schedule 14.07.2018
comment
Я так не ответил, потому что думал, что this.tabGroup.selectedIndex не вызовет обнаружение изменений внутри компонента. Если вы посмотрите исходный код в github, функция установки не запускает обновление. github.com/angular/material2/ blob / master / src / lib / tabs / - person Reactgular; 15.07.2018

<mat-tab-group> считывает ввод [selectedIndex] только при первом создании компонента. Впоследствии привязка вывода (selectedIndex) позволяет отслеживать изменения вкладок.

Я думаю, вы устанавливаете значение 1 до того, как эта вкладка существует.

Проблема в том, что *ngFor впоследствии создает дочерние mat-tab компоненты. Когда <mat-tab-group> получает уведомление о том, что дочерние элементы изменили, по умолчанию используется вкладка первая.

Единственный обходной путь, о котором я знаю, - это инициировать изменение привязки [selectedIndex] после создания дочерних <mat-tab> компонентов.

Обновите свой компонент, чтобы у него было свойство:

public selectedIndex: number = 0;

Используйте это как привязку для ввода selectedIndex:

<mat-tab-group class="col-10 offset-1" 
               (selectedTabChange)="onTabChanged($event)" 
               [selectedIndex]="selectedIndex">

Внедрите эти зависимости в свой компонент:

  public constructor(private change: ChangeDetectorRef) {}

Обновите подписку, чтобы изменить выбранный индекс после того, как *ngFor завершит обновление документа.

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();
    });
});
person Reactgular    schedule 14.07.2018
comment
[selectedIndex] = selectedIndex и this.selectedIndex = 1; подход сработал для меня. Спасибо. - person Rajkumar M; 24.11.2020