Skip to content

Commit 7069b44

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 7069b44

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
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: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,32 @@ 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+
if (this._updateChangeSubscription) {
172+
this._updateChangeSubscription();
173+
}
174+
},
175+
});
176+
}
177+
}
178+
179+
private _sortingDataAccessor: (data: T, sortHeaderId: string) => string | number = (
155180
data: T,
156181
sortHeaderId: string,
157182
): string | number => {
@@ -258,6 +283,7 @@ export class _MatTableDataSource<
258283
constructor(initialData: T[] = []) {
259284
super();
260285
this._data = new BehaviorSubject<T[]>(initialData);
286+
this._defineSortingDataAccessor();
261287
this._updateChangeSubscription();
262288
}
263289

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)