Angular 2 - 反应式表单验证消息

wei*_*ian 10 reactive-forms angular

我的目标是将所有验证消息放在组件而不是html文件中

我有一个注册页面,下面是字段:

public buildRegisterForm() {
this.userForm = this.fb.group({
  firstName: ['', [Validators.required, Validators.minLength(3)]],
  lastName: ['', [Validators.required, Validators.maxLength(50)]],
  emailGroup: this.fb.group({
    email: ['', [Validators.required, Validators.pattern(this.emailPattern)]],
    retypeEmail: ['', Validators.required],
  }, { validator: formMatcherValidator('email', 'retypeEmail') }),
  passwordGroup: this.fb.group({
    password: ['', [Validators.required, strongPasswordValidator()]],
    retypePassword: ['', Validators.required],
  }, { validator: formMatcherValidator('password', 'retypePassword')}),
});
}
Run Code Online (Sandbox Code Playgroud)

我正在按照本教程链接实现我想要的,即将所有验证消息放在组件文件而不是html文件中.

export const validationMessages = {
'firstName': {
'required': 'Your first name is required.',
'minlength': 'Your first name must be at least 3 characters long.'
},
'lastName': {
'required': 'Your last name is required.',
'minlength': 'Your last name must be less than 50 characters long.'
},
'emailGroup': {
  'email': {
      'required': 'Your email is required',
      'pattern': 'Your login email does not seem to be a valid email address.'
     },
 'retypeEmail': {
      'required': 'Your retype email is required',
      'match': 'The email provided do not match.'
   },
},
'passwordGroup':{
     'password': {
         'required': 'Your password is required',
         'strongPassword': 'Your password must be between 8 - 15 characters and must contain at least three of the following: upper case letter, lower case letter, number, symbol.'
     },
   'retypePassword': {
       'required': 'Your retype password is required',
        'match': 'The password provided do not match.'
  }
}
Run Code Online (Sandbox Code Playgroud)


onValueChanged方法

private onValueChanged(data?: any) {
if (!this.userForm) { return; }
const form = this.userForm;

// tslint:disable-next-line:forin
for (const field in this.formErrors) {
  // clear previous error message (if any)
  this.formErrors[field] = '';
  let control = form.get(field);
  // console.log("control", control.dirty);

  console.log("controlEmail", control);
  if (control && (control.dirty || control.touched) && control.invalid) {
    let messages = validationMessages[field];
    // tslint:disable-next-line:forin
    for (const key in control.errors) {
      this.formErrors[field] += messages[key] + ' ';
    }
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

当我有多个formBuider组或嵌套对象时,此方法不起作用.这1的任何提示?
与此类似如何验证具有嵌套表单组的反应形式?

AJT*_*T82 8

我看到它的方式,你需要在onValueChanged(data)-method中创建一个嵌套循环.由于你有很多嵌套组,我不打算复制它.但嵌套循环是通用的,因此它适用于所有组.但这是一个只有一个嵌套组而不是几个嵌套组的例子.我正在使用英雄的例子.

嵌套组名称是group,并且调用其中的formcontrol child.

formErrors因此,代码中使用的内容应该child在内部group:

formErrors = {
  'name': '',
  'power': '',
  'group':{
    'child': ''
  }
};
Run Code Online (Sandbox Code Playgroud)

因此,您必须记住在模板中添加验证时,您需要使用:

<div *ngIf="formErrors.group.child">
   {{ formErrors.group.child }}
</div>
Run Code Online (Sandbox Code Playgroud)

验证消息不在内部group,但与其他验证消息一样:

validationMessages = {
  'name': {
    'required': 'Name is required.',
  },
  'power': {
    'required': 'Power is required.'
  },
  'child': {
    'required': 'Child is required.',
  }
};
Run Code Online (Sandbox Code Playgroud)

最后,修改onValueChanges:

onValueChanged(data?: any) {
  if (!this.heroForm) { return; }
  const form = this.heroForm;

  // iterate toplevel of formErrors
  for (const field in this.formErrors) {
    // check if the field corresponds a formgroup (controls is present)
    if(form.get(field).controls ) {
      // if yes, iterate the inner formfields
      for(const subfield in form.get(field).controls) {
        // in this example corresponds = "child", reset the error messages
        this.formErrors[field][subfield] = '';
        // now access the actual formfield
        const control = form.get(field).controls[subfield];
        // validate and show appropriate error message
        if (control && control.dirty && !control.valid) {
          const messages = this.validationMessages[subfield];
          for (const key in control.errors) {
            this.formErrors[field][subfield] += messages[key] + ' ';
          }
        }
      }
    } 
    // does not contain a nested formgroup, so just iterate like before making changes to this method
    else {
      const control = form.get(field);
      this.formErrors[field] = '';
      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          this.formErrors[field] += messages[key] + ' ';
        }
      } 
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,一个DEMO :)

Plunker

你必须要记住,在你的情况下,这是有效的,但如果在嵌套组中有嵌套组,这将不起作用,那么你必须在另一个循环onValueChanges,但你没有那个问题;)