访问自定义表单控件的有效值
Posted
技术标签:
【中文标题】访问自定义表单控件的有效值【英文标题】:Access valid value of custom form control 【发布时间】:2018-01-14 02:55:59 【问题描述】:我创建了代表密码表单控件的自定义组件(以下代码已简化)。
密码组件 (html)
<form [formGroup]="passwordForm">
...
<input formControlName="password" type="password">
</form>
密码组件 (ts)
...
@Component(
selector: 'password',
templateUrl: './password.component.html',
styleUrls: ['./password.component.css'],
providers: [
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PasswordComponent),
multi: true
]
)
export class PasswordComponent implements ControlValueAccessor
passwordForm: FormGroup;
onChange = (password: string) => ;
onTouched = () => ;
constructor()
this.passwordForm = new FormGroup(
...
password: new FormControl('')
);
this.passwordForm.valueChanges.subscribe(data => this.onChange(this.value));
get value(): string
return this.passwordForm.get('password').value;
writeValue(password: string): void
this.passwordForm.get('password').setValue(password);
this.onChange(this.value);
registerOnChange(fn: any): void this.onChange = fn;
registerOnTouched(fn: any): void this.onTouched = fn;
setDisabledState?(isDisabled: boolean): void
我在其他组件中使用它而不是标准输入元素:
<form [formGroup]="userForm">
...
<password formControlName="password"></password>
</form>
验证器来自外部形式(它们没有在 PasswordComponent 中定义)
this.userForm = fb.group(
...
password: ['', [Validators.minLength(10), Validators.maxLength(100)]]
);
我的问题是:如何从 PasswordComponent 中获取 <password>
元素的有效性?我想根据有效性对其进行风格化。换句话说,我怎样才能从代表该控件的 PasswordComponent 中获取 userForm 的“密码”控件的有效性。
【问题讨论】:
【参考方案1】:因为我们无法直接从 DI 系统获取 NgControl
实例,因为我们会遇到循环依赖错误。下图显示了如果我们在自定义值访问器中注入 NgControl
会发生这种情况的原因:
现在应该清楚我们有NgControl -> FormControlName -> ValueAccessor -> CustomValueAccessor -> NgControl
循环依赖
要解决这个问题,您可以利用Injector
来实现:
component.ts
import NgControl from '@angular/forms';
export class PasswordComponent implements ControlValueAccessor
...
ngControl: NgControl;
constructor(private inj: Injector)
...
ngOnInit()
this.ngControl = this.inj.get(NgControl)
template.html
ngControl.control.valid
Plunker Example
【讨论】:
这就像一个魅力,但它看起来很丑,还是只有我这么认为?它看起来像一个非常基本的用例 您能否更详细地解释一下这里发生了什么?为什么会出现循环 dep 错误?为什么喷油器没有? 感谢您直观地了解事物的设置方式。 Angular 文档将受益于这些事情! 当我this.inj.get(NgControl)
我得到一个FormControlName
这是无用的,因为formControlname.parent.control
是一个formgroup
并且“我不知道”哪个控件是“自定义控件”。
我的生命周期错误。在ngAfterViewInit
我可以阅读name
然后得到正确的控制。 _parent
是私人的。【参考方案2】:
解决此问题的另一种方法是从提供程序中删除 NG_VALUE_ACCESSOR 并注入 NgControl。使用 NgControl 实例,组件将被注册为 ValueAccessor。
constructor(
...,
@Optional() @Self() public ngControl: NgControl,
...,
)
// Setting the value accessor directly (instead of using
// the providers) to avoid running into a circular import.
if (this.ngControl != null) this.ngControl.valueAccessor = this;
【讨论】:
以上是关于访问自定义表单控件的有效值的主要内容,如果未能解决你的问题,请参考以下文章