2017-09-27 109 views
0

我創建了一個名爲threeNumbers的自定義驗證程序,它只能接受三位數字。但是,當我將其應用於在username領域,它拋出一個錯誤ERROR TypeError: Cannot read property 'length' of nullformGroup 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> 
+0

你可以添加你的模板嗎? – yurzui

+0

[自定義驗證器](https://angular.io/guide/form-validation#custom-validators)文檔。 –

+0

如果(control.value && control.value.length <3 ...' – yurzui

回答

0

像內置的驗證,你並不需要調用threeNumbers,只是把它作爲一個參考this.fb.group

您不需要bind調用,因爲Angular會在內部調用它。將其更改爲:

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引用您的類的實例化版本。

本質上刪除括號。

由於驗證器不應該依賴任何局部變量,因此您可以多花一分鐘,並使threeNumbers方法成爲靜態方法 - Angular默認驗證器是靜態的。

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

我也建議傳遞一個空字符串'',而不是null到每個控件初始化。這有助於保持一致的狀態。注:在那個筆記上,你有一個'typeof'檢查,如果這個FormControl綁定到一個輸入,那麼typeof將始終是一個字符串。

我做了修改 - 參見上文。