Это действительно связано с поведением рендеринга ngFor.
Точнее, если массив, используемый в ngFor, изменяет ссылки на элементы этого массива (и мы не предоставили настраиваемую функцию trackBy для переопределениясравнение), тогда Angular распознает эти изменения и повторно отобразит представление.
Угловые формы часто могут запускать метод AbstractControl.updateValueAndValidity
для всей иерархии элементов управления.
FormControl -> parent -> FormGroup -> parent -> FormArray -> parent -> FormGroup
Для FormGroup он вызываетследующий метод:
_updateValue(): void { (this as{value: any}).value = this._reduceValue(); }
, который в основном создает новый объект, т. е. {name: 'Alice'}
При следующем запуске он заменит текущее значение новым.
{name: 'Alice'} !== {name: 'Alice'}
Это точноэта угловая разница по умолчанию распознается в директиве ngForOf.
Вы можете спросить?
Тогда почему я не вижу разницы с в этом примере в StackBlitz?
В этом примере проблема все еще существует, но ее не видно с первого взгляда.
|username password
/\
click here(it works)
username password
/\
then click here(it doesn't since the dom was rerendered)
Разница между вашим примером и приведенным выше примером заключается в том, что вы используете элементы управления материалом и триггер AbstractControl.updateValueAndValidity
происходит раньше.
Так в чем же решение?
1) Упомянутое ранее свойство trackBy
trackByFn(index) {
return index;
}
*ngFor="let data of form.controls.offers?.value; let i = index; trackBy: trackByFn"
Пример Stackblitz
2) Присвойте this.form.controls.offers.value
свойству компонента и используйте его.
arr;
...
this.arr = this.form.controls.offers.value;
*ngFor="let data of arr; let i = index;"
Пример Stackblitz