Skip to content

Commit

Permalink
fix(tabs): maintain selected tab when new tabs are added or removed
Browse files Browse the repository at this point in the history
Maintains the `selectedIndex` of the current tab when a new tab is added or removed. Previously, changing the amount of tabs would shift the array, causing a different tab to be selected.

Fixes #7738.
  • Loading branch information
crisbeto committed Dec 27, 2017
1 parent c3d7cd9 commit 3fb1921
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/lib/tabs/tab-group.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,12 @@ describe('MatTabGroup', () => {
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);

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

fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});
fixture.detectChanges();

tabs = component._tabs.toArray();
expect(tabs[0].origin).toBeLessThan(0);
});
Expand All @@ -303,6 +305,47 @@ describe('MatTabGroup', () => {
expect(component.selectedIndex).toBe(numberOfTabs - 2);
});


it('should maintain the selected tab if a new tab is added', () => {
fixture.detectChanges();
const component: MatTabGroup =
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;

fixture.componentInstance.selectedIndex = 1;
fixture.detectChanges();

// Add a new tab at the beginning.
fixture.componentInstance.tabs.unshift({label: 'New tab', content: 'at the start'});
fixture.detectChanges();

expect(component.selectedIndex).toBe(2);
expect(component._tabs.toArray()[2].isActive).toBe(true);
});


it('should maintain the selected tab if a tab is removed', () => {
// Add a couple of tabs so we have more to work with.
fixture.componentInstance.tabs.push(
{label: 'New tab', content: 'with new content'},
{label: 'Another new tab', content: 'with newer content'}
);

// Select the second-to-last tab.
fixture.componentInstance.selectedIndex = 3;
fixture.detectChanges();

const component: MatTabGroup =
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;

// Remove a tab right before the selected one.
fixture.componentInstance.tabs.splice(2, 1);
fixture.detectChanges();

expect(component.selectedIndex).toBe(1);
expect(component._tabs.toArray()[1].isActive).toBe(true);
});


});

describe('async tabs', () => {
Expand Down
10 changes: 10 additions & 0 deletions src/lib/tabs/tab-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ export class MatTabGroup extends _MatTabGroupMixinBase implements AfterContentIn
// Subscribe to changes in the amount of tabs, in order to be
// able to re-render the content as new tabs are added or removed.
this._tabsSubscription = this._tabs.changes.subscribe(() => {
const tabs = this._tabs.toArray();

// 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;
break;
}
}

this._subscribeToTabLabels();
this._changeDetectorRef.markForCheck();
});
Expand Down

0 comments on commit 3fb1921

Please sign in to comment.