为什么自定义验证器不起作用 [英] why is custom validator not working

查看:33
本文介绍了为什么自定义验证器不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个名为 threeNumbers 的自定义验证器,它的作用是只接受三位数字.但是当我将它应用到 username 字段时,它会抛出一个错误 ERROR TypeError: Cannot read property 'length' of nullformGroup 需要一个 FormGroup 实例.请传入一个.

 ngOnInit() {//在响应式表单的类中指定的表单控件验证this.courseForm = this.fb.group({用户名:[null, [Validators.required, this.threeNumbers.bind(this)]],电子邮件:[null, [Validators.required, Validators.pattern('([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+)\\.([a-zA-Z]{2,5})')]],地址:[null, [Validators.required, Validators.minLength(10), Validators.maxLength(100)]],选择:[null,[Validators.required]]});this.dropDownArr = this.dropdown.getData();//this.personDetail = {//  姓名: '',//  电子邮件: '',//  地址: '',//选择的课程:''//};this.personDetail = this.fieldData.getPersonData();console.log(this.courseForm);}三号(控件:FormControl){if (control.value.length < 3 && typeof control.value !== 'number') {return { '大于 3 个数字':true };}返回空;}//HTML模板<!-- 具有三个输入和一个下拉列表的表单,该下拉列表在初始化时使用来自服务的数据进行初始化并使用 min 和 maxlength 进行验证--><section class="容器"><!-- ngSubmit 在提交表单时调用函数 onSubmit --><form class="form-horizo​​ntal" (ngSubmit)='onSubmit()' [formGroup]='courseForm'><div class="form-group"><label for="inputUsername" class="col-sm-2 control-label">用户名</label><div class="col-sm-10"><input type="text" class="form-control" id="inputUsername" placeholder="Username" formControlName="username" name="name"[ngClass]="{inValid: !courseForm.get('username').valid && courseForm.get('username').touched, valid: courseForm.get('username').valid &&courseForm.get('username').touched}"><span class="help-block" *ngIf="!courseForm.get('username').valid && courseForm.get('username').touched">请输入有效的用户名</span>

<!-- 用户名输入到此结束--><div class="form-group"><label for="inputEmail" class="col-sm-2 control-label">Email</label><div class="col-sm-10"><!-- 基于验证应用的 CSS 类 --><input type="email" class="form-control" id="inputEmail" placeholder="Email" formControlName="email" name="email" [ngClass]="{inValid: !courseForm.get('email').valid && courseForm.get('email').touched, valid: courseForm.get('email').valid && courseForm.get('email').touched}"><span class="help-block" *ngIf="!courseForm.get('email').valid && courseForm.get('email').touched">请输入有效的电子邮件</span>

<!-- 电子邮件输入到此结束--><div class="form-group"><label for="inputAddress" class="col-sm-2 control-label">Address</label><div class="col-sm-10"><input type="text" class="form-control" id="inputAddress" placeholder="你的地址" formControlName="address" name="address"[ngClass]="{inValid: !courseForm.get('address').valid && courseForm.get('address').touched, valid: courseForm.get('address').valid &&courseForm.get('address').touched}"><!--在 MinLength 和 MaxLength 验证上显示错误消息--><span class="help-block" *ngIf="courseForm.get('address')?.errors?.required && courseForm.get('address').touched">请输入您的地址</跨度><span class="help-block" *ngIf="(courseForm.get('address')?.errors?.minlength?.requiredLength !== courseForm.get('address')?.errors?.minlength?.actualLength) && courseForm.get('address')?.touched">地址长度至少应为 10 个字符</span>

<!-- 地址输入到此结束--><div class="form-group"><label for="sel1" class="col-sm-2 control-label">选择课程</label><div class="col-sm-10"><select class="form-control" id="sel1" formControlName="select" [(ngModel)]="selectedOption" name="select" [ngClass]="{inValid: !courseForm.get('select').valid && courseForm.get('select').touched, valid: courseForm.get('select').valid && courseForm.get('select').touched}"><option [value]="selectedOption" [disabled]="true">选择您的课程</option><option *ngFor="let data of dropDownArr; index as i" [ngValue]="data.course">{{data.course}}</option></选择><span class="help-block" *ngIf="!courseForm.get('select').valid && courseForm.get('select').touched">请选择课程</span>

<!-- 选择输入在此结束--><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><button type="submit" class="btn btn-default" [disabled]=!courseForm.valid>提交</button><button type="button" class="btn btn-default" (click)="resetForm(f)">重置</button>

<!-- 提交和重置按钮到此结束--></表单></节><!-- 部分在视图中显示提交的表单数据--><section class="容器"><div class="panel panel-default"><div class="panel-heading">注册用户</div><!-- 列表组--><ul class="list-group"><li class="list-group-item" *ngFor="let person of peopleList">用户名:&nbsp;&nbsp;{{person.name}} &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;电子邮件:&nbsp;&nbsp;{{person.email}}&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;地址:&nbsp;&nbsp;{{person.address}} &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;选择的课程:&nbsp;&nbsp;{{person.chosenCourse}}</li>

</节>

解决方案

和内置验证器一样,不需要调用threeNumbers,只需将它作为对this的引用传递即可.fb.group:

您不需要 bind 调用,因为 Angular 会在内部调用它.改为:

this.courseForm = this.fb.group({用户名:['',[Validators.required,this.threeNumbers]],电子邮件:['', [Validators.required, Validators.pattern('([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+)\\.([a-zA-Z]{2,5})')]],地址:['', [Validators.required, Validators.minLength(10), Validators.maxLength(100)]],选择:['',[Validators.required]]});

目前,您正在绑定 this 属性.在本例中,this 指的是您的类的实例化版本.

基本上去掉括号.

你可以加倍努力,让你的 threeNumbers 方法是静态的,因为验证器不应该依赖于任何局部变量 - Angular 默认的验证器是静态的.

public static ThreeNumbers(control: FormControl) {if (control.value.length < 3 && typeof control.value !== 'number') {return { '大于 3 个数字':true };}返回空;}

我还建议向每个控件初始化传递一个空字符串 '',而不是 null.这有助于保持一致的状态.备注在那一点上,你有一个typeof"检查,如果这个 FormControl 绑定到一个输入,那么 typeof 将始终是一个字符串.

我已作出修正 - 见上文.

I created a custom Validator called threeNumbers what it does is that it accepts only three digit numbers. But when I applied it to the username field it throws an error ERROR TypeError: Cannot read property 'length' of null and formGroup expects a FormGroup instance. Please pass one in.

  ngOnInit() {
    // form controls validation specicified in the class for the Reactive Forms
    this.courseForm = this.fb.group({
      username: [null, [Validators.required, this.threeNumbers.bind(this)]],
      email: [null, [Validators.required, Validators.pattern('([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+)\\.([a-zA-Z]{2,5})')]],
      address: [null, [Validators.required, Validators.minLength(10), Validators.maxLength(100)]],
      select: [null, [Validators.required]]
    });
    this.dropDownArr = this.dropdown.getData();
    // this.personDetail = {
    //   name: '',
    //   email: '',
    //   address: '',
    //   chosenCourse: ''
    // };
    this.personDetail = this.fieldData.getPersonData();
    console.log(this.courseForm);
  }

  threeNumbers(control: FormControl) {
    if (control.value.length < 3 && typeof control.value !== 'number') {
      return { 'greater than 3 numbers': true };
    }
    return null;
  }

//HTML template

<!-- Form with three inputs and one dropdown which intializes with data from service on intialization and validates with min and maxlength-->
<section class="container">
  <!-- ngSubmit calls the function onSubmit on submitting the form  -->
  <form class="form-horizontal" (ngSubmit)='onSubmit()' [formGroup]='courseForm'>
    <div class="form-group">
      <label for="inputUsername" class="col-sm-2 control-label">Username</label>
      <div class="col-sm-10">
        <input type="text" class="form-control" id="inputUsername" placeholder="Username" formControlName="username" name="name"
          [ngClass]="{inValid: !courseForm.get('username').valid && courseForm.get('username').touched, valid: courseForm.get('username').valid && courseForm.get('username').touched}">
        <span class="help-block" *ngIf="!courseForm.get('username').valid && courseForm.get('username').touched">Please enter a valid username</span>
      </div>
    </div>
    <!-- username input ends here -->
    <div class="form-group">
      <label for="inputEmail" class="col-sm-2 control-label">Email</label>
      <div class="col-sm-10">
        <!-- CSS class applied based on validation -->
        <input type="email" class="form-control" id="inputEmail" placeholder="Email" formControlName="email" name="email" [ngClass]="{inValid: !courseForm.get('email').valid && courseForm.get('email').touched, valid: courseForm.get('email').valid && courseForm.get('email').touched}">
        <span class="help-block" *ngIf="!courseForm.get('email').valid && courseForm.get('email').touched">Please Enter a valid email</span>
      </div>
    </div>
    <!-- email input ends here -->
    <div class="form-group">
      <label for="inputAddress" class="col-sm-2 control-label">Address</label>
      <div class="col-sm-10">
        <input type="text" class="form-control" id="inputAddress" placeholder="Your Address" formControlName="address" name="address"
          [ngClass]="{inValid: !courseForm.get('address').valid && courseForm.get('address').touched, valid: courseForm.get('address').valid && courseForm.get('address').touched}">
        <!--Display error message on MinLength and MaxLength Validation-->
        <span class="help-block" *ngIf="courseForm.get('address')?.errors?.required && courseForm.get('address').touched">Please Enter Your Address</span>
        <span class="help-block" *ngIf="(courseForm.get('address')?.errors?.minlength?.requiredLength !== courseForm.get('address')?.errors?.minlength?.actualLength) && courseForm.get('address')?.touched">Address should be at least 10 characters long</span>
      </div>
    </div>
    <!-- address input ends here -->
    <div class="form-group">
      <label for="sel1" class="col-sm-2 control-label">Choose Course</label>
      <div class="col-sm-10">
        <select class="form-control" id="sel1" formControlName="select" [(ngModel)]="selectedOption" name="select" [ngClass]="{inValid: !courseForm.get('select').valid && courseForm.get('select').touched, valid: courseForm.get('select').valid && courseForm.get('select').touched}">
          <option [value]="selectedOption" [disabled]="true">Choose Your Course</option>
          <option *ngFor="let data of dropDownArr; index as i"  [ngValue]="data.course">{{data.course}}</option>          
        </select>
        <span class="help-block" *ngIf="!courseForm.get('select').valid && courseForm.get('select').touched">Please choose a Course</span>
      </div>
    </div>
    <!-- select input ends here -->
    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <button type="submit" class="btn btn-default" [disabled]=!courseForm.valid>Submit</button>
        <button type="button" class="btn btn-default" (click)="resetForm(f)">Reset</button>
      </div>
    </div>
    <!-- submit and reset buttons ends here -->
  </form>
</section>
<!-- section displays the submited form data in the view -->
<section class="container">
  <div class="panel panel-default">
    <div class="panel-heading">Registered users</div>

    <!-- List group -->
    <ul class="list-group">
      <li class="list-group-item" *ngFor="let person of personsList">username:&nbsp;&nbsp;{{person.name}} &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp; email:&nbsp;&nbsp;{{person.email}}
        &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp; Address: &nbsp;&nbsp;{{person.address}} &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
        Course Chosen: &nbsp;&nbsp;{{person.chosenCourse}}</li>
    </ul>
  </div>
</section>

解决方案

Like the built-in validators, you do not need to call threeNumbers, just pass it as a reference to this.fb.group:

You do not need the bind call, as Angular calls this internally. Change it to:

this.courseForm = this.fb.group({
  username: ['', [Validators.required, this.threeNumbers]],
  email: ['', [Validators.required, Validators.pattern('([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+)\\.([a-zA-Z]{2,5})')]],
  address: ['', [Validators.required, Validators.minLength(10), Validators.maxLength(100)]],
  select: ['', [Validators.required]]
});

At the moment, you're binding the this property. In this instance, this refers to your instantiated version of the class.

Remove the parenthesis essentially.

You could go the extra mile and make your threeNumbers method static since a validator should not depend on any local variables - the Angular default validators are static.

public static ThreeNumbers(control: FormControl) {
  if (control.value.length < 3 && typeof control.value !== 'number') {
    return { 'greater than 3 numbers': true };
  }
  return null;
}

I would also recommend passing an empty string '', instead of null to each control initialisation. This helps with a consistent state. N.b. on that note, you have a 'typeof' check, if this FormControl is bound to an input, then typeof will always be a string.

I have made amends - see above.

这篇关于为什么自定义验证器不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆