Angular 2 - 响应式(Reactive)表单验证消息

标签 angular angular-reactive-forms

我的目标是将所有验证消息放在组件中而不是 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')}),
});
}

我正在学习本教程 link实现我想要的是 将我所有的验证消息放在组件文件而不是 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.'
  }
}


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] + ' ';
    }
  }
 }
}

当我有多个 formBuider 组或嵌套对象时,此方法不起作用。这 1 有什么建议吗?
类似于此 How to validate reactive forms with nested form groups?

最佳答案

在我看来,您需要在 onValueChanged(data) 方法中创建一个嵌套循环。由于您有很多嵌套组,因此我不会复制它。但是嵌套循环是通用的,因此它适用于您的所有组。但这是一个只有一个嵌套组而不是多个嵌套组的示例。我正在使用英雄示例。

嵌套的组名是group,里面的formcontrol叫做child

因此,代码中使用的

formErrors 应该在 group 中包含 child:

formErrors = {
  'name': '',
  'power': '',
  'group':{
    'child': ''
  }
};

所以一定要记住,在模板中添加验证时,需要使用:

<div *ngIf="formErrors.group.child">
   {{ formErrors.group.child }}
</div>

验证消息不会在 group 中,但就像其他验证消息一样:

validationMessages = {
  'name': {
    'required': 'Name is required.',
  },
  'power': {
    'required': 'Power is required.'
  },
  'child': {
    'required': 'Child is required.',
  }
};

最后,修改后的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] + ' ';
        }
      } 
    }
  }
}

最后,一个DEMO :)

Plunker

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

关于Angular 2 - 响应式(Reactive)表单验证消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43383341/

相关文章:

javascript - 请求的资源 : Mean stack 上不存在 'Access-Control-Allow-Origin' header

javascript - 传单库的类型是什么意思?

javascript - 在 Angular 应用程序中全局使用 ngx-toastr

javascript - Angular Reactive Form Control valueChanges 获取值更改字段名称,上一个值和当前值

Angular 4获取Select控件的Selected选项的文本

typescript - 角度 react 形式控制错误: how to read the error object

Angular + Jest : Error: Uncaught (in promise): Failed to load C:footer. component.html

Angular - 如何使用响应式(Reactive)表单动态默认选中复选框

angular - 同时使用 ValidatorFn 和 AbstractControlOptions 实例化 FormControl

javascript - Angular Material 表 : how to pass/submit selected rows upon button click?