我有多个组件,每个组件都有一些输入,选择和其他表单元素。这所有元素都是使用模板驱动的形式开发的。
但之前它的开发不是在组件方面,所以我们能够检查表单状态。现在我们已经按组件划分了所有内容但验证我们无法得到它。
我有两个问题。
为了将子组件表单元素添加到父组件,我使用 ControlValueAccessor ,这是正确的方法吗?在我的子组件中,我有多个表单控件,如input,select和other。
输入元素上需要的简单验证,它在子组件内部不起作用。我该怎么办?
这是Plunkr,它主要证明了我想要实现的目标。
@Component({
selector: 'my-child',
template: `
<h1>Child</h1>
<input [ngModel]="firstName" (ngModelChange)="firstSet($event)" required>
<input [ngModel]="lastName" (ngModelChange)="lastSet($event)" required> <!-- required validation is not working -->
`,
providers: [
{provide: NG_VALUE_ACCESSOR, useExisting: Child, multi: true}
]
})
export class Child implements ControlValueAccessor, OnChanges {
private firstName: string,
private lastName: string;
fn: (value: any) => void;
constructor(){
}
writeValue(value: any) {
console.log("write value");
console.log(value);
if(value){
this.firstName = value.firstName;
this.lastName = value.lastName;
}
}
registerOnChange(fn: (value: any) => void) {
this.fn = fn;
}
registerOnTouched() {}
firstSet(v: string){
this.firstName = v;
this.fn({
firstName: this.firstName,
lastName: this.lastName
});
}
lastSet(v: string){
this.lastName = v;
this.fn({
firstName: this.firstName,
lastName: this.lastName
});
}
}
如果您发现错误的方法请提及哪种方法正确?
注意:请建议适用于模板驱动表单的解决方案。,我忘了提及我使用的是Angular 2.4.8版本。
答案 0 :(得分:0)
不确定为什么不使用Reactive Forms - 它们几乎都是为验证而设计的。
您也可以混合搭配,因为您使用的是ngModel,所以您不会被锁定使用模板驱动的表单。
您可以仅使用Reactive Forms进行验证。
component.ts
form: FormGroup;
constructor(fb : FormBuilder) {
this.form = fb.group({
'firstName' : ['', Validators.required],
'lastName' : ['', Validators.required]
})
}
hasError(n: string){
return this.form.get(n).hasError('required') && this.form.get(n).touched;
}
template.html
<h1>Child</h1>
<input [ngModel]="firstName" name="firstName" [formControl]="form.get('firstName')" required>
<div *ngIf="hasError('firstName')">This field is required</div>
<input [ngModel]="lastName" name="lastName" [formControl]="form.get('lastName')" required> <!-- required validation is not working -->
<div *ngIf="hasError('lastName')">This field is required</div>