#angular #core-js
Вопрос:
У меня возникла проблема после обновления angular и зависимостей до более поздних версий.
Приложение работает как и раньше, но я увидел сообщение об ошибке в консоли, которого у меня раньше не было:
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'.
Похоже, у меня эта проблема с более поздней версией «core-js».
После поиска в Интернете кажется, что ошибка может возникнуть с @ViewChild, используемым для автозаполнения, но я не понимаю, в чем дело. Кроме того, похоже, что код, ответственный за эту ошибку, следующий:
- В html первого компонента я использую компонент с автозаполнением:
<mat-form-field>
<mat-placeholder>...</mat-placeholder>
<input class="t-myClass" type="text" matInput
[formControl]="myFormGroup.controls['myField']" (change)="resetValidity()"
[matAutocomplete]="myAutocomplete.autocomplete" #myField>
<app-my-autocomplete #myAutocomplete="appMyAutocomplete"
[inputFormControl]="myFormGroup.controls['myField']" [inputElement]="myField">
</app-my-autocomplete>
</mat-form-field>
- В компоненте с компонентом автозаполнения у меня есть это:
export class MyAutocompleteComponent implements OnInit, OnChanges, OnDestroy {
@Input()
inputFormControl: FormControl;
@Input()
inputElement: HTMLInputElement;
@ViewChild('autocomplete')
autocomplete: MatAutocomplete;
filteredObjects: Observable<MyElement[]>;
//inputFormSubscription: Subscription;
constructor(
private myElementService: MyElementService,
...
) { }
ngOnChanges() {
}
onSelection() {
if (this.inputElement) {
// Need to create a timeout cause the input is selected just after the option selection
setTimeout(() => {
this.inputElement.blur();
}, 0);
}
}
ngOnInit() {
//this.inputFormSubscription = this.inputFormControl.valueChanges.subscribe(val => this.filteredObjects = this.geographyElementService.getGeographyElements(val));
this.filteredObjects = this.inputFormControl.valueChanges.pipe(switchMap(val => this.geographyElementService.getGeographyElements(val)));
}
ngOnDestroy() {
//this.inputFormSubscription.unsubscribe();
}
...
}
- HTML, связанный с этим компонентом (с автозаполнением), является:
<mat-autocomplete #autocomplete [displayWith]="label.bind(this)" panelWidth="240px">
<mat-option *ngFor="let object of filteredObjects | async " [value]="object" (onSelectionChange)="onSelection()">
{{ object.code }} - {{ object.description }}
</mat-option>
</mat-autocomplete>
При отладке я обнаружил, что текущее значение, соответствующее ошибке, является объектом MatAutocomplete, поэтому кажется, что он подтверждает, что это именно этот код, но я не понимаю, почему, потому что код работает.
Не могли бы вы помочь мне решить эту проблему, пожалуйста?
Изменить: Я обновил код в соответствии с данным ответом, но ошибка все равно возникает.
Комментарии:
1. Зачем вам подписываться на изменение значения элемента управления формой внутри цикла
ngOnChanges
жизненного цикла? Этот параметр вызывается несколько раз в течение срока службы компонента (при каждом изменении свойства). Можете ли вы попробовать перенести этоngOnInit
вместо этого? Во-вторых, этой подпиской необходимо управлять, вам нужно отказаться от подписки, когда компонент будет уничтожен, иначе у вас произойдет утечка памяти.2. И вам даже не нужна эта подписка: вместо этого сделайте
this.filteredObjects = this.inputFormControl.valueChanges.pipe(switchMap(//...
это .3. Спасибо. Я сделал подобное изменение в методе ngOnInit (): this.filteredObjects = this.inputFormControl.valueChanges.pipe(switchMap(val => this.filteredObjects = this.myElementService.getMyElements(val))); Но ошибка все равно появляется.
4. Как
filteredObjects
они потребляются?5. Я обновил сообщение с помощью html — кода для компонента с автозаполнением. Он потребляется в ngFor.
Ответ №1:
Решение состояло в том, чтобы использовать статику со значением true для автозаполнения:
@ViewChild('autocomplete', { static: true })
autocomplete: MatAutocomplete;