Angular 9 - 自定义指令中的 NgModel 改变了 Angular 7 的行为
Angular 9 - NgModel in custom directive changed behaviour from Angular 7
我正在将一个大型应用程序升级到 Angular 9 并启用 Ivy 编译,并且遇到了似乎是将 NgModel 注入自定义指令的行为发生变化
使用该指令时,在使用IVY编译时注入的NgModel在版本7和版本8/9之间是不同的。
禁用 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();
}
};
从 @Directive
属性中删除 providers: [NgModel]
应该可以解决问题。
我正在将一个大型应用程序升级到 Angular 9 并启用 Ivy 编译,并且遇到了似乎是将 NgModel 注入自定义指令的行为发生变化
使用该指令时,在使用IVY编译时注入的NgModel在版本7和版本8/9之间是不同的。
禁用 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();
}
};
从 @Directive
属性中删除 providers: [NgModel]
应该可以解决问题。