Обратите внимание: Вам нужно обернуть this.dataSource.sort = this.sort
в setTimeout()
, чтобы установить ссылку в цикле дайджеста, без него @ViewChild(MatSort) sort: MatSort
не определено из-за *ngIf
.
ngOnChanges() {
const ELEMENT_DATA1: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
{ position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
{ position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
{ position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
{ position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
{ position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];
this.dataSource.data = ELEMENT_DATA1;
console.log(this.sort) //undefined
setTimeout(() => {
console.log(this.sort) //not undefined
this.dataSource.sort = this.sort;
})
}
Stackblitz
https://stackblitz.com/edit/angular-table-sort-not-working-pv8yap?embed=1&file=app/table-sorting-example.ts
Цикл дайджеста - это термин, определенный в днях AngularJS ... см. Этот SO-ответдля получения дополнительной информации .... Поверьте, теперь это чаще называют Change Detection
Angular определяет концепцию так называемого цикла дайджеста.Этот цикл можно рассматривать как цикл, во время которого Angular проверяет, есть ли какие-либо изменения во всех переменных, наблюдаемых всеми $ scopes.Поэтому, если в вашем контроллере определен $ scope.myVar, и эта переменная была помечена для отслеживания, то вы явно указываете Angular отслеживать изменения на myVar на каждой итерации цикла.
Angular - что запускает цикл дайджеста для двухсторонних привязок данных?
См. Этот неугловой специфический ответ, почему setTmiout()
работает.
AБраузер должен делать сразу несколько вещей, и только одна из них - выполнять JavaScript.Но одна из вещей, для которой очень часто используется JavaScript - это попросить браузер создать элемент отображения.Часто предполагается, что это делается синхронно (в частности, поскольку JavaScript не выполняется параллельно), но нет никакой гарантии, что это так, и JavaScript не имеет четко определенного механизма ожидания.
Решение состоит в том, чтобы«приостановить» выполнение JavaScript, чтобы потоки рендеринга наверстали упущенное.И это эффект, который делает setTimeout () с таймаутом 0.Это похоже на выход потока / процесса в C. Хотя кажется, что он говорит «запустите это немедленно», на самом деле он дает браузеру возможность завершить некоторые вещи, не связанные с JavaScript, которые ожидали завершения, прежде чем приступить к этому новому фрагменту JavaScript..
Почему setTimeout (fn, 0) иногда полезен?
В итоге
Обнаружение цикла / изменения дайджеста обычно относится к задаче, не связанной с Angular, такой как рендеринг элемента представления и т. Д. ... в этом примере ваш ngOnchange()
не ожидал потоков рендеринга, созданных вашим *ngIf
, становящимся истинным,завершить в браузере ... и пытался привязать ссылку @ViewChild
view до того, как она была на самом деле в DOM ...
- Причина, по которой console.log был не определен
- А другой внутри
setTimeout()
не было
Обтекание этой строки кода в setTimeout()
заставило его ждать, пока браузер завершит свою задачу рендеринга, созданную вашим *ngIf
.