Skip to content

Commit 1e164b6

Browse files
crisbetojosephperrott
authored andcommitted
fix(tabs): maintain selected tab when new tabs are added or removed (#9132)
1 parent ce90bed commit 1e164b6

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/lib/tabs/tab-group.spec.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,14 +333,17 @@ describe('MatTabGroup', () => {
333333
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);
334334

335335
// Add a new tab in the beginning and select it, expect an origin < than 0 (animate left)
336-
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});
337336
fixture.componentInstance.selectedIndex = 0;
338337
fixture.detectChanges();
339338
tick();
340339

340+
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});
341+
fixture.detectChanges();
342+
tick();
343+
341344
tabs = component._tabs.toArray();
342345
expect(tabs[0].origin).toBeLessThan(0);
343-
}));
346+
}));
344347

345348

346349
it('should update selected index if the last tab removed while selected', fakeAsync(() => {
@@ -360,6 +363,47 @@ describe('MatTabGroup', () => {
360363
expect(component.selectedIndex).toBe(numberOfTabs - 2);
361364
}));
362365

366+
367+
it('should maintain the selected tab if a new tab is added', () => {
368+
fixture.detectChanges();
369+
const component: MatTabGroup =
370+
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
371+
372+
fixture.componentInstance.selectedIndex = 1;
373+
fixture.detectChanges();
374+
375+
// Add a new tab at the beginning.
376+
fixture.componentInstance.tabs.unshift({label: 'New tab', content: 'at the start'});
377+
fixture.detectChanges();
378+
379+
expect(component.selectedIndex).toBe(2);
380+
expect(component._tabs.toArray()[2].isActive).toBe(true);
381+
});
382+
383+
384+
it('should maintain the selected tab if a tab is removed', () => {
385+
// Add a couple of tabs so we have more to work with.
386+
fixture.componentInstance.tabs.push(
387+
{label: 'New tab', content: 'with new content'},
388+
{label: 'Another new tab', content: 'with newer content'}
389+
);
390+
391+
// Select the second-to-last tab.
392+
fixture.componentInstance.selectedIndex = 3;
393+
fixture.detectChanges();
394+
395+
const component: MatTabGroup =
396+
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
397+
398+
// Remove a tab right before the selected one.
399+
fixture.componentInstance.tabs.splice(2, 1);
400+
fixture.detectChanges();
401+
402+
expect(component.selectedIndex).toBe(1);
403+
expect(component._tabs.toArray()[1].isActive).toBe(true);
404+
});
405+
406+
363407
});
364408

365409
describe('async tabs', () => {

src/lib/tabs/tab-group.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ export class MatTabGroup extends _MatTabGroupMixinBase implements AfterContentIn
200200
// Subscribe to changes in the amount of tabs, in order to be
201201
// able to re-render the content as new tabs are added or removed.
202202
this._tabsSubscription = this._tabs.changes.subscribe(() => {
203+
const tabs = this._tabs.toArray();
204+
205+
// Maintain the previously-selected tab if a new tab is added or removed.
206+
for (let i = 0; i < tabs.length; i++) {
207+
if (tabs[i].isActive) {
208+
this._indexToSelect = i;
209+
break;
210+
}
211+
}
212+
203213
this._subscribeToTabLabels();
204214
this._changeDetectorRef.markForCheck();
205215
});

0 commit comments

Comments
 (0)