问题描述
我有一条指令,用于检查表单组件是使用Reactive Forms还是由Template-Driven创建的。我使用它来维护使用同一指令的其他组件之间的兼容性。在Angular 8中所有工作都很好,但在Angular 9中却没有。
在我的指令中,我有一个方法来获取和设置字段值,将文件状态设置为脏或被触摸,但是要做到这一点,我有条件知道组件使用了什么形式。
不幸的是,在Angular 9中,我无法做到这一点,因为我不知道该怎么做。拜托,如果有人可以帮助我,我会很感激。
遵循我的指令
@Directive({
selector: '[appSelect2Cities]',})
export class Select2CitiesDirective implements OnChanges,AfterContentChecked,AfterViewInit {
input: any;
// Cast one of the types to a variable
@ContentChild(NgModel,{ static: false }) model: NgModel;
@ContentChild(FormControlName,{ static: false }) control: FormControlName;
// ... some code here
ngOnChanges(changes: SimpleChanges): void {
if (this.model) {
// ... some code here
} else if (this.control) {
// ... some code here
}
}
ngAfterViewInit(): void {
this.input = this.model || this.control;
if (this.input === undefined) { // <-- Always undefined here
throw new Error('That directive needs to be used by ngModel or FormControlName');
}
this.initializeSelect2();
}
// ... some code here
}
我使用反应式表单的示例
<select
appSelect2Cities
class="form-control"
formControlName="cities"
[value]="citiesValue"
placeholder="Select a City"
(itemSelected)="onCitySelected($event)"
>
</select>
和我使用模板驱动的示例
<select
appSelect2Cities
class="form-control"
name="city"
[(ngModel)]="address.city"
>
</select>
解决方法
最后,我找到了解决问题的答案!
我不完全知道为什么@ContentChild
在这种情况下不能以相同的方式工作,但是我认为这与Angular团队所做的更改有关,以解决查询中的错误和令人惊讶的行为。看到https://angular.io/guide/static-query-migration
在我的情况下,解决方案只是在构造函数中声明NgModel
和FormControlName
,而不是像波纹管那样使用@ContentChold
@Directive({
selector: '[appSelect2Cities]',})
export class Select2CitiesDirective implements OnChanges,AfterContentChecked,AfterViewInit {
input: any;
constructor(@Optional() private model: NgModel,@Optional() private control: FormControlName) {}
// ... some code here
ngOnChanges(changes: SimpleChanges): void {
if (this.model) {
// ... some code here
} else if (this.control) {
// ... some code here
}
}
ngAfterViewInit(): void {
this.input = this.model || this.control;
if (this.input === undefined) { // <-- Now works fine
throw new Error('That directive needs to be used by ngModel or FormControlName');
}
this.initializeSelect2();
}
// ... some code here
}