【发布时间】:2020-01-31 03:42:01
【问题描述】:
我有一个嵌套表单组件,其中有一个 <input> 字段设置为与 formControlName="nested" 一起使用。验证器在父 FormControl 上设置,如下所示:
form = this.fb.group({
value: ['', [Validators.required, Validators.minLength(3)]],
nested: ['', [Validators.required, Validators.minLength(3)]],
});
我想将状态从父 FormControl 传播到嵌套 <input>,因此它的反应方式与常规的非嵌套 <input> 相同,即它并单击提交(control.markAsTouched()),状态设置为无效,CSS 样式ng-invalid 已设置。
我设法获得了 部分胜利 after reading this SO post 使用以下代码订阅父控件的状态更改,但“触摸”嵌套输入会将其恢复为 VALID 并单击提交将没有设置ng-invalid 样式。
@ViewChild('tbNgModel', {static: false}) tbNgModel: NgModel;
private isAlive = true;
constructor(@Optional() @Self() public ngControl: NgControl, private cdr: ChangeDetectorRef) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
ngAfterViewInit(): void {
this.ngControl.statusChanges.pipe(
takeWhile(() => this.isAlive)
).subscribe(status => {
console.log('Status changed: ', status, 'Errors: ', this.ngControl.errors);
this.tbNgModel.control.setErrors(this.ngControl.errors);
this.cdr.detectChanges();
});
this.ngControl.control.updateValueAndValidity(); // to force emit initial value
}
Stackblitz reproduction of my problem
我如何才能真正将状态传播到嵌套控件,同时仅在父级 FormControl 上设置验证器?
最终解决方案
来自@Eliseo 的回答和this other SO post,这是我最终完成的实现(它对我有用,但可能还有更好的方法)
component.ts
constructor(@Optional() @Self() public ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
...
getValidationCss() {
if (!this.ngControl) return {};
return {
'ng-invalid': this.ngControl.invalid,
'is-invalid': this.ngControl.invalid && this.ngControl.touched,
'ng-valid': this.ngControl.valid,
'ng-touched': this.ngControl.touched,
'ng-untouched': this.ngControl.untouched,
'ng-pristine': this.ngControl.pristine,
'ng-dirty': this.ngControl.dirty,
};
}
component.html
...
<input #tb class="form-control" [ngClass]="getValidationCss()" ...>
...
【问题讨论】: