Упаковщик вкладок угловых материалов - добавление новой вкладки не отражается в пользовательском интерфейсе
Я пытаюсь создать обертку вокруг MatTabs
который выставляет все свойства MatTabs
и наткнулся на этот вопрос: угловые вкладки материала не работают с компонентом оболочки. Я добавил другие свойства вкладок и события к нему. События, кажется, запускаются правильно.
Проблема возникает, когда я добавляю новую вкладку. Массив обновляется, но интерфейс остается прежним.
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);
}
Пользовательские вкладки StackBlitz.
В идеале я хочу раскрыть все функции, которые MatTabs
предоставляет из коробки, а затем некоторые.
1 ответ
Итак, причина, по которой вкладки не загружаются, заключается в коде в компоненте пользовательских вкладок. ngViewAfterInit()
функция. Это было инициализировано, но это все. Итак this.tabGroup
никогда не обновляется с текущими вкладками и, следовательно, не отражается в пользовательском интерфейсе. Поэтому я добавил подписку, чтобы следить за изменением вкладок, и использую ту же логику (которая, я не уверен, на 100% верна, но она выполняет свою работу).
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.selected.value на -1, а затем переключаюсь обратно на правильную вкладку, так что это немного некрасиво, но, по крайней мере, работает.