Ответ 1
Попробуйте создать глубокую копию, выполнив
this.arr = Object.assign({}, NEW_VALUE);
У меня есть массив объектов (назовем его arr
). В одном из моих компонентных входов в методе (change)
я изменяю один из этих атрибутов объекта, но в представлении (*ngFor
) ничего не меняется. Я читал, что обнаружение изменений Angular2 не проверяет содержимое массивов или объектов, поэтому я пробовал эти:
this.arr = this.arr.slice();
и
this.arr = [...this.arr];
Но представление не меняется, оно по-прежнему показывает старый атрибут. В методе (change)
с console.log()
я получил правильный массив. Странно, но это работает: this.arr = [];
Я также пробовал NgZone
и markForCheck()
.
Попробуйте создать глубокую копию, выполнив
this.arr = Object.assign({}, NEW_VALUE);
Вы также можете использовать опцию trackBy
в своем выражении *ngFor
, предоставляя уникальный идентификатор для каждого элемента в массиве. Это делает вас на 100% ответственным за обнаружение изменений, поэтому обновляйте это (уникальное) свойство каждый раз, когда изменяется элемент в массиве. Затем Angular будет перерисовывать список только в том случае, если какой-либо элемент в вашем массиве получил другое свойство trackBy
:
*ngFor="let item of (itemList$ | async); trackBy: trackItem"
или же:
*ngFor="let item of itemList; trackBy: trackItem"
где:
trackItem
- это публичный метод в вашем компоненте:
public trackItem (index: number, item: Item) {
return item.trackId;
}
Поскольку вы упомянули, что вы уже пробовали markForCheck()
, вы должны попробовать вместо этого использовать DetectionChanges (это то, что у меня сработало, а markForCheck не сработало). Для тех, кому нужны шаги:
Добавьте ChangeDetectorRef в ваш импорт:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
Добавьте ChangeDetectorRef в ваш конструктор:
constructor(
private changeDetection: ChangeDetectorRef
) { }
Затем на следующей строке после обновления массива:
this.changeDetection.detectChanges();
Я решил эту ошибку, добавив директиву changDetection в @component следующим образом
@Component({
selector: 'app-page',
templateUrl: './page.component.html',
styleUrls: ['./page.component.scss'],
changeDetection: ChangeDetectionStrategy.Default
})
Вам также нужно импортировать его
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
Есть две стратегии на Push и Default
OnPush использует стратегию CheckOnce, что означает, что автоматическое обнаружение изменений отключается до тех пор, пока не будет активировано снова, если для стратегии задано значение Default (CheckAlways). Обнаружение изменений все еще может быть вызвано явно.
в то время как Default использует стратегию CheckAlways, в которой обнаружение изменений происходит автоматически до явной деактивации.
Исходные документы
Если кто-нибудь еще столкнется с моей ситуацией, убедитесь, что компонент, который обновляется, является той же копией, что и отображаемый.
Я использовал @ViewChild(MyComponent, { static: true }) private test: MyComponent
для передачи данных в компонент с помощью ngfor. (В моем случае это привело к блокировке другой копии, о которой я не знал)
Мне удалось это исправить, добавив атрибут #mycomp
к тегу моего компонента в html и изменив вышеприведенное значение на @ViewChild('mycomp', { static: true }) private test: MyComponent