diff --git a/src/material/table/table-data-source.spec.ts b/src/material/table/table-data-source.spec.ts index 8bcba15cf3c3..8082a7c7020f 100644 --- a/src/material/table/table-data-source.spec.ts +++ b/src/material/table/table-data-source.spec.ts @@ -5,8 +5,6 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {Component, ViewChild} from '@angular/core'; describe('MatTableDataSource', () => { - const dataSource = new MatTableDataSource(); - beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [MatSortModule, NoopAnimationsModule], @@ -15,13 +13,16 @@ describe('MatTableDataSource', () => { })); describe('sort', () => { + let dataSource: MatTableDataSource; let fixture: ComponentFixture; let sort: MatSort; beforeEach(() => { fixture = TestBed.createComponent(MatSortApp); fixture.detectChanges(); + dataSource = new MatTableDataSource(); sort = fixture.componentInstance.sort; + dataSource.sort = sort; }); /** Test the data source's `sortData` function. */ @@ -51,6 +52,19 @@ describe('MatTableDataSource', () => { it('should be able to correctly sort an array of strings and numbers', () => { testSortWithValues([3, 'apples', 'bananas', 'cherries', 'lemons', 'strawberries']); }); + + it('should unsubscribe from the re-render stream when disconnected', () => { + const spy = spyOn(dataSource._renderChangesSubscription!, 'unsubscribe'); + dataSource.disconnect(); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should re-subscribe to the sort stream when re-connecting after being disconnected', () => { + dataSource.disconnect(); + const spy = spyOn(fixture.componentInstance.sort.sortChange, 'subscribe'); + dataSource.connect(); + expect(spy).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/src/material/table/table-data-source.ts b/src/material/table/table-data-source.ts index af29105cec4a..c30bd0e68b6b 100644 --- a/src/material/table/table-data-source.ts +++ b/src/material/table/table-data-source.ts @@ -53,7 +53,7 @@ export class _MatTableDataSource extends DataSource { * Subscription to the changes that should trigger an update to the table's rendered rows, such * as filtering, sorting, pagination, or base data changes. */ - _renderChangesSubscription = Subscription.EMPTY; + _renderChangesSubscription: Subscription|null = null; /** * The filtered set of data that has been matched by the filter string, or all the data if there @@ -244,7 +244,7 @@ export class _MatTableDataSource extends DataSource { const paginatedData = combineLatest([orderedData, pageChange]) .pipe(map(([data]) => this._pageData(data))); // Watched for paged data changes and send the result to the table to render. - this._renderChangesSubscription.unsubscribe(); + this._renderChangesSubscription?.unsubscribe(); this._renderChangesSubscription = paginatedData.subscribe(data => this._renderData.next(data)); } @@ -321,13 +321,22 @@ export class _MatTableDataSource extends DataSource { * Used by the MatTable. Called when it connects to the data source. * @docs-private */ - connect() { return this._renderData; } + connect() { + if (!this._renderChangesSubscription) { + this._updateChangeSubscription(); + } + + return this._renderData; + } /** - * Used by the MatTable. Called when it is destroyed. No-op. + * Used by the MatTable. Called when it disconnects from the data source. * @docs-private */ - disconnect() { } + disconnect() { + this._renderChangesSubscription?.unsubscribe(); + this._renderChangesSubscription = null; + } } /** diff --git a/tools/public_api_guard/material/table.d.ts b/tools/public_api_guard/material/table.d.ts index acfb24ab2e74..2c1ad2b23a67 100644 --- a/tools/public_api_guard/material/table.d.ts +++ b/tools/public_api_guard/material/table.d.ts @@ -1,7 +1,7 @@ export declare const _MAT_TEXT_COLUMN_TEMPLATE = "\n \n \n {{headerText}}\n \n \n {{dataAccessor(data, name)}}\n \n \n"; export declare class _MatTableDataSource extends DataSource { - _renderChangesSubscription: Subscription; + _renderChangesSubscription: Subscription | null; get data(): T[]; set data(data: T[]); get filter(): string;