为什么自定义验证程序不起作用

为什么自定义验证程序不起作用

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

问题描述

我创建了一个名为threeNumbers的自定义验证程序,它的作用是只接受三个数字.但是,当我将其应用于username字段时,它会引发错误ERROR TypeError: Cannot read property 'length' of nullformGroup expects a FormGroup instance. Please pass one in.

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 andformGroup 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>

推荐答案

就像内置验证器一样,您无需调用threeNumbers,只需将其作为对this.fb.group的引用即可:

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

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

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]]
});

目前,您正在绑定this属性.在这种情况下,this引用您的类的实例化版本.

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

基本上删除括号.

由于验证器不应该依赖任何局部变量-Angular默认验证器是静态的,因此您可以花更多的精力并使threeNumbers方法变为静态.

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;
}

我还建议将空字符串''而不是null传递给每个控件初始化.这有助于保持一致的状态. N.b.在该注释上,您有一个'typeof'检查,如果此FormControl绑定到输入,则typeof将始终是字符串.

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.

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

08-23 09:14