Forms 角度2:带有验证的自定义输入组件(反应式/模型驱动方法)

Forms 角度2:带有验证的自定义输入组件(反应式/模型驱动方法),forms,validation,angular,Forms,Validation,Angular,我必须使用被动/模型驱动方法和验证在组件内部和外部创建一个组件(以及组件内部的更多元素,但这不是问题,也不是示例的一部分) 我已经创建了这个组件,它工作得很好,我的问题是formControl(在子控件和父控件内部)在验证或类似于触摸的状态时都不同步。例如,如果键入的字符串超过10个字符,则表单中的表单控件仍然有效 //我们的根应用程序组件 从“@angular/core”导入{Component,Input} 导入{ FormControl, FormGroup, ControlValueA

我必须使用被动/模型驱动方法验证在组件内部和外部创建一个组件(以及组件内部的更多元素,但这不是问题,也不是示例的一部分)

我已经创建了这个组件,它工作得很好,我的问题是formControl(在子控件和父控件内部)在验证或类似于触摸的状态时都不同步。例如,如果键入的字符串超过10个字符,则表单中的表单控件仍然有效

//我们的根应用程序组件
从“@angular/core”导入{Component,Input}
导入{
FormControl,
FormGroup,
ControlValueAccessor,
NG_值存取器,
验证器
}从“@angular/forms”开始;
@组成部分({
选择器:“我的孩子”,
模板:`
小孩
`,
供应商:[
{provide:NG\u VALUE\u访问器,useExisting:Child,multi:true}
]
})
导出类子实现ControlValueAccessor{
childControl=新表单控件(“”,Validators.maxLength(10));
writeValue(值:任意){
this.childControl.setValue(值);
}
registerOnChange(fn:(值:any)=>void){
this.childControl.valueChanges.subscribe(fn);
}
寄存器(){}
}
@组成部分({
选择器:“我的应用程序”,
模板:`
你好{{name}
登记
{{form.value | json}}
`
})
导出类应用程序{
表单=新表单组({
用户名:新FormControl('username',验证器。必需)
});
构造函数(){
this.name='Angular2';
}
你好{
console.log(this.form.controls['username'])
}
}

我不知道如何以正确的方式解决这个问题

存在一个从Angular到将验证转发给父级的验证程序接口。您需要使用它并使用forwardRef向组件装饰器的providers数组提供NG_验证器:

{
  provide: NG_VALIDATORS,
  useExisting: CustomInputComponent,
  multi: true
}
您的组件需要实现验证程序接口:

class CustomInputComponent implements ControlValueAccessor, Validator,...
您必须提供验证程序接口方法的实现,至少是验证方法的实现:

  validate(control: AbstractControl): ValidationErrors | null {
    return this.formGroup.controls['anyControl'].invalid ? { 'anyControlInvalid': true } : null;
  } 
当验证器的输入发生变化时,还有另一种同步验证器的方法:

  registerOnValidatorChange(fn: () => void): void {
    this.validatorChange = fn;
  }

存在一个从Angular到将验证转发给父级的验证程序接口。您需要使用它并使用forwardRef向组件装饰器的providers数组提供NG_验证器:

{
  provide: NG_VALIDATORS,
  useExisting: CustomInputComponent,
  multi: true
}
您的组件需要实现验证程序接口:

class CustomInputComponent implements ControlValueAccessor, Validator,...
您必须提供验证程序接口方法的实现,至少是验证方法的实现:

  validate(control: AbstractControl): ValidationErrors | null {
    return this.formGroup.controls['anyControl'].invalid ? { 'anyControlInvalid': true } : null;
  } 
当验证器的输入发生变化时,还有另一种同步验证器的方法:

  registerOnValidatorChange(fn: () => void): void {
    this.validatorChange = fn;
  }

尝试在子级中使用@Input(),父级将向子级提供值,子级将处理信息并验证它。类似于@Input()valuefromparent;childControl=new FormControl(this.valuefromparent,Validators.maxLength(10));我尝试了你的建议,但仍然没有达到预期的效果:我想我明白你现在想做的,孩子理解这个价值并验证了它。问题是家长不知道孩子做了什么,您将需要触发一个从子级到父级的事件emmiter。使用EventEmmiter,我可以实现我的父级知道验证。我的问题还在于我的孩子不知道我父母的FormControl。您知道如何访问child中parent的FormControl吗?您知道您正在实例化两个控件吗?它们不同步的原因是因为它们不是同一个对象。请尝试在子对象中使用@Input(),父对象将向子对象提供值,子对象将处理并验证该信息。类似于@Input()valuefromparent;childControl=new FormControl(this.valuefromparent,Validators.maxLength(10));我尝试了你的建议,但仍然没有达到预期的效果:我想我明白你现在想做的,孩子理解这个价值并验证了它。问题是家长不知道孩子做了什么,您将需要触发一个从子级到父级的事件emmiter。使用EventEmmiter,我可以实现我的父级知道验证。我的问题还在于我的孩子不知道我父母的FormControl。您知道如何访问child中parent的FormControl吗?您知道您正在实例化两个控件吗?它们不同步的原因是它们不是同一个对象。