From 0186a039a31a8e99a0fe4c0ebabc268a02d9a48d Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 11 Jul 2018 17:03:37 +0200 Subject: [PATCH] fix(tabs): don't fire change event when amount of tabs changes (#12097) Fixes the tab group firing its `selectedTabChange` event when the amount of tabs changes, which might throw the consumer into an infinite loop if they're adding new tabs inside the callback. Fixes #12084. --- src/lib/tabs/tab-group.spec.ts | 14 ++++++++++++++ src/lib/tabs/tab-group.ts | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) 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; } }