Я частично прошёл модернизацию большого приложения до Angular 9 с включенной компиляцией Ivy, и натолкнулся на то, что кажется изменением в поведении при введении NgModel в пользовательскую директиву
При использовании эта директива, внедряемая NgModel, отличается между версией 7 и версией 8/9, когда используется компиляция IVY.
ЭТОГО НЕ происходит, когда компиляция Ivy отключена.
Директива (tabSelect)
import { Directive, AfterViewInit, OnDestroy, Optional } from '@angular/core';
import { NgModel } from "@angular/forms";
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
@Directive({
selector: '[tabSelect]',
providers: [NgModel]
})
export class TabSelectDirective implements AfterViewInit, OnDestroy {
observable: any;
onChange: any;
constructor(@Optional()
private autoTrigger: MatAutocompleteTrigger,
private ngModel: NgModel) { }
ngAfterViewInit() {
this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
if (this.autoTrigger.activeOption && this.autoTrigger.activeOption.value) {
if (this.ngModel.model !== this.autoTrigger.activeOption.value) {
this.ngModel.update.emit(this.autoTrigger.activeOption.value);
this.autoTrigger.autocomplete.optionSelected.emit();
}
} else {
console.log(this.ngModel);
console.log(this.autoTrigger);
if (!this.ngModel.viewModel || this.ngModel.viewModel === "")
this.ngModel.update.emit(null);
};
});
}
ngOnDestroy() {
this.observable.unsubscribe();
}
};
Использование директивы в HTML
<mat-form-field appearance="outline" color="primary" class="mat-input-no-validation pull-right"
style="width: 130px; margin-left: 10px">
<mat-label>Document Group</mat-label>
<input matInput
placeholder="Search.."
name="documentGroupInput"
spellcheck="false"
[(ngModel)]="documentNode.documentGroup"
[matAutocomplete]="documentGroupAuto"
#documentGroupCtrl="ngModel"
tabSelect />
<div class="small-progress-spinner-container" [hidden]="!documentGroupSearching">
<mat-progress-spinner [diameter]="15" [mode]="'indeterminate'"></mat-progress-spinner>
</div>
<mat-autocomplete #documentGroupAuto="matAutocomplete">
<mat-option *ngFor="let documentGroup of documentGroupResults; trackBy:formatters.trackIndex" [value]="documentGroup">
<div class="autocomplete-option">
{{ documentGroup }}
</div>
</mat-option>
</mat-autocomplete>
</mat-form-field>
При проверке NgModel, который вводится в Директиву, в Angular 7 мы видим имя элемента управления
NgModel {_parent: NgForm, name: "documentGroupInput", valueAccessor: MatAutocompleteTrigger, _rawValidators: Array(0), _rawAsyncValidators: Array(0), …}
Когда в Angular 9 мы не
NgModel {_parent: NgForm, name: null, valueAccessor: MatAutocompleteTrigger, _rawValidators: Array(0), _rawAsyncValidators: Array(0), …}
Это приводит меня к мысли, что введенный NgModel на самом деле не является моделью сам элемент управления в Ivy, и это поддерживается методом присвоения значения и выдачи измененного события, которое больше не работает
Есть идеи, что изменилось и как я могу решить эту проблему?
Спасибо
РЕДАКТИРОВАТЬ: - Фиксированный код
import { Directive, AfterViewInit, OnDestroy, Optional } from '@angular/core';
import { NgModel } from "@angular/forms";
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
@Directive({
selector: '[tabSelect][ngModel]',
providers: []
})
export class TabSelectDirective implements AfterViewInit, OnDestroy {
observable: any;
onChange: any;
constructor(@Optional()
private autoTrigger: MatAutocompleteTrigger,
private ngModel: NgModel) { }
ngAfterViewInit() {
console.log(this.ngModel);
this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
if (this.autoTrigger.activeOption && this.autoTrigger.activeOption.value) {
if (this.ngModel.model !== this.autoTrigger.activeOption.value) {
this.ngModel.update.emit(this.autoTrigger.activeOption.value);
this.autoTrigger.autocomplete.optionSelected.emit();
}
} else {
console.log(this.ngModel);
console.log(this.autoTrigger);
if (!this.ngModel.viewModel || this.ngModel.viewModel === "")
this.ngModel.update.emit(null);
};
});
}
ngOnDestroy() {
this.observable.unsubscribe();
}
};