Skip to content

Commit d68145c

Browse files
committed
fix(material/table): data not being re-rendered when sortingDataAccessor is changed
Fixes the table's data not re-rendering when a new `sortingDataAccessor` is assigned to the data source. Fixes #15888.
1 parent 29ac6cf commit d68145c

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

src/material-experimental/mdc-table/table.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,18 @@ describe('MDC-based MatTable', () => {
447447
]);
448448
});
449449

450+
it('should emit if the sortingDataAccessor changes', () => {
451+
const spy = jasmine.createSpy('data changes spy');
452+
const subscription = dataSource.connect().subscribe(spy);
453+
454+
// Reset the `calls` since the data source emits upon subscription as well.
455+
spy.calls.reset();
456+
dataSource.sortingDataAccessor = () => '';
457+
458+
expect(spy).toHaveBeenCalled();
459+
subscription.unsubscribe();
460+
});
461+
450462
it('should by default correctly sort an empty string', () => {
451463
// Activate column A sort
452464
dataSource.data[0].a = ' ';

src/material/table/table-data-source.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class _MatTableDataSource<
7878
* For example, a 'selectAll()' function would likely want to select the set of filtered data
7979
* shown to the user rather than all the data.
8080
*/
81-
filteredData: T[];
81+
filteredData: T[] = [];
8282

8383
/** Array of data that should be rendered by the table, where each object represents one row. */
8484
get data() {
@@ -151,7 +151,30 @@ export class _MatTableDataSource<
151151
* @param data Data object that is being accessed.
152152
* @param sortHeaderId The name of the column that represents the data.
153153
*/
154-
sortingDataAccessor: (data: T, sortHeaderId: string) => string | number = (
154+
sortingDataAccessor: (data: T, sortHeaderId: string) => string | number;
155+
156+
/**
157+
* `sortingDataAccessor` is currently a regular property, however we need to know when it is
158+
* updated so that we can re-render the data. The problem is that we can't turn it into a
159+
* getter/setter, because it'll break existing users that define the accessor by extending the
160+
* class and initializing it to a new value. This is a workaround that'll preserve the old
161+
* behavior for users who override it and apply the fix for ones who don't. Eventually we should
162+
* reconcile these behaviors.
163+
* @breaking-change 15.0.0
164+
*/
165+
private _defineSortingDataAccessor() {
166+
if (!this.sortingDataAccessor) {
167+
Object.defineProperty(this, 'sortingDataAccessor', {
168+
get: () => this._sortingDataAccessor,
169+
set: accessor => {
170+
this._sortingDataAccessor = accessor;
171+
this._updateChangeSubscription();
172+
},
173+
});
174+
}
175+
}
176+
177+
private _sortingDataAccessor: (data: T, sortHeaderId: string) => string | number = (
155178
data: T,
156179
sortHeaderId: string,
157180
): string | number => {
@@ -258,7 +281,6 @@ export class _MatTableDataSource<
258281
constructor(initialData: T[] = []) {
259282
super();
260283
this._data = new BehaviorSubject<T[]>(initialData);
261-
this._updateChangeSubscription();
262284
}
263285

264286
/**
@@ -267,6 +289,8 @@ export class _MatTableDataSource<
267289
* the provided base data and send it to the table for rendering.
268290
*/
269291
_updateChangeSubscription() {
292+
this._defineSortingDataAccessor();
293+
270294
// Sorting and/or pagination should be watched if MatSort and/or MatPaginator are provided.
271295
// The events should emit whenever the component emits a change or initializes, or if no
272296
// component is provided, a stream with just a null event should be provided.
@@ -385,6 +409,8 @@ export class _MatTableDataSource<
385409
* @docs-private
386410
*/
387411
connect() {
412+
this._defineSortingDataAccessor();
413+
388414
if (!this._renderChangesSubscription) {
389415
this._updateChangeSubscription();
390416
}

src/material/table/table.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,18 @@ describe('MatTable', () => {
432432
]);
433433
});
434434

435+
it('should emit if the sortingDataAccessor changes', () => {
436+
const spy = jasmine.createSpy('data changes spy');
437+
const subscription = dataSource.connect().subscribe(spy);
438+
439+
// Reset the `calls` since the data source emits upon subscription as well.
440+
spy.calls.reset();
441+
dataSource.sortingDataAccessor = () => '';
442+
443+
expect(spy).toHaveBeenCalled();
444+
subscription.unsubscribe();
445+
});
446+
435447
it('should by default correctly sort an empty string', () => {
436448
// Activate column A sort
437449
dataSource.data[0].a = ' ';

0 commit comments

Comments
 (0)