diff --git a/src/lib/tabs/tab-group.spec.ts b/src/lib/tabs/tab-group.spec.ts index 77d762455b4..3063045f575 100644 --- a/src/lib/tabs/tab-group.spec.ts +++ b/src/lib/tabs/tab-group.spec.ts @@ -403,6 +403,20 @@ describe('MatTabGroup', () => { expect(component._tabs.toArray()[1].isActive).toBe(true); }); + it('should not fire `selectedTabChange` when the amount of tabs changes', fakeAsync(() => { + fixture.detectChanges(); + fixture.componentInstance.selectedIndex = 1; + fixture.detectChanges(); + + // Add a new tab at the beginning. + spyOn(fixture.componentInstance, 'handleSelection'); + fixture.componentInstance.tabs.unshift({label: 'New tab', content: 'at the start'}); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + + expect(fixture.componentInstance.handleSelection).not.toHaveBeenCalled(); + })); }); diff --git a/src/lib/tabs/tab-group.ts b/src/lib/tabs/tab-group.ts index 5d45471f1ee..3f5f0e971c7 100644 --- a/src/lib/tabs/tab-group.ts +++ b/src/lib/tabs/tab-group.ts @@ -205,7 +205,10 @@ export class MatTabGroup extends _MatTabGroupMixinBase implements AfterContentIn // Maintain the previously-selected tab if a new tab is added or removed. for (let i = 0; i < tabs.length; i++) { if (tabs[i].isActive) { - this._indexToSelect = i; + // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed + // event, otherwise the consumer may end up in an infinite loop in some edge cases like + // adding a tab within the `selectedIndexChange` event. + this._indexToSelect = this._selectedIndex = i; break; } }