最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular custom async validator not working - Stack Overflow

programmeradmin1浏览0评论

Here is the demo plnkr. I am trying to implement a custom async validator for a OTP input which has a text box and a verify button. I want to validate the input only when the user clicks on the verify OTP button or form submit button. Currently validation is happening on the text change event and it's not working. Form HTML:

<form [formGroup]="registrationForm" (ngSubmit)="registrationForm.valid && submitRegistration(registrationForm.value)" novalidate>
  <fieldset class="form-group">
    <label for="e-mail">Mobile</label>
    <div class="input-group">
      <input type="text" class="form-control" placeholder="Mobile" formControlName="mobile">
      <span class="input-group-btn">
        <button class="btn btn-secondary" type="button">Send OTP</button>
      </span>
    </div>
    <div class="form-text error" *ngIf="registrationForm.controls.mobile.touched">
      <div *ngIf="registrationForm.controls.mobile.hasError('required')">Mobile is required.</div>
    </div>
  </fieldset>
  <fieldset class="form-group">
    <label for="e-mail">Verify OTP</label>
    <div class="input-group">
      <input type="text" class="form-control" placeholder="OTP" formControlName="otp">
      <span class="input-group-btn">
        <button class="btn btn-secondary" (click)="veryOTPAsyn(otp)" type="button">Verify</button>
      </span>
    </div>
    <div class="form-text error" *ngIf="registrationForm.controls.otp.touched">
      <div *ngIf="registrationForm.controls.otp.hasError('required')">OTP is required.</div>
      <div *ngIf="registrationForm.controls.otp.hasError('invalidOtp')">OTP is invalid.</div>
    </div>
  </fieldset>
  <button class='btn btn-primary' type='submit' [disabled]='!registrationForm.valid'>Submit Registration Form</button>
</form>

Form Component:

export class ExampleFormComponent {
  registrationForm: FormGroup;

  constructor(public fb: FormBuilder) {
    // Example use of FormBuilder, FormGroups, and FormControls
    this.registrationForm = fb.group({
      mobile: ['', Validators.required],
      otp: ['', Validatorspose([Validators.required, this.veryOTPAsyn.bind(this)])],
      dob: ['', Validators.required],
      email: ['', Validatorspose([Validators.required,  emailValidator])],
      password: ['', Validators.required],
      confirmPassword: ['', Validators.required],
      firstName: ['', Validators.required],
      lastName: ['', Validators.required]
    }, {validator: matchingPasswords('password', 'confirmPassword')})

  }

  submitRegistration(value: Object): void {
    console.log(value);
  }

  veryOTPAsyn(otpControl: FormControl): Promise<any> {
    console.log(otpControl)
    console.log(otpControl.hasError('invalidOtp'))
    return new Promise<any>(
      (resolve, reject) => {
        setTimeout(() => {
          resolve({invalidOtp:true});
        }, 500);
      });
  }

}

Here is the demo plnkr. I am trying to implement a custom async validator for a OTP input which has a text box and a verify button. I want to validate the input only when the user clicks on the verify OTP button or form submit button. Currently validation is happening on the text change event and it's not working. Form HTML:

<form [formGroup]="registrationForm" (ngSubmit)="registrationForm.valid && submitRegistration(registrationForm.value)" novalidate>
  <fieldset class="form-group">
    <label for="e-mail">Mobile</label>
    <div class="input-group">
      <input type="text" class="form-control" placeholder="Mobile" formControlName="mobile">
      <span class="input-group-btn">
        <button class="btn btn-secondary" type="button">Send OTP</button>
      </span>
    </div>
    <div class="form-text error" *ngIf="registrationForm.controls.mobile.touched">
      <div *ngIf="registrationForm.controls.mobile.hasError('required')">Mobile is required.</div>
    </div>
  </fieldset>
  <fieldset class="form-group">
    <label for="e-mail">Verify OTP</label>
    <div class="input-group">
      <input type="text" class="form-control" placeholder="OTP" formControlName="otp">
      <span class="input-group-btn">
        <button class="btn btn-secondary" (click)="veryOTPAsyn(otp)" type="button">Verify</button>
      </span>
    </div>
    <div class="form-text error" *ngIf="registrationForm.controls.otp.touched">
      <div *ngIf="registrationForm.controls.otp.hasError('required')">OTP is required.</div>
      <div *ngIf="registrationForm.controls.otp.hasError('invalidOtp')">OTP is invalid.</div>
    </div>
  </fieldset>
  <button class='btn btn-primary' type='submit' [disabled]='!registrationForm.valid'>Submit Registration Form</button>
</form>

Form Component:

export class ExampleFormComponent {
  registrationForm: FormGroup;

  constructor(public fb: FormBuilder) {
    // Example use of FormBuilder, FormGroups, and FormControls
    this.registrationForm = fb.group({
      mobile: ['', Validators.required],
      otp: ['', Validators.pose([Validators.required, this.veryOTPAsyn.bind(this)])],
      dob: ['', Validators.required],
      email: ['', Validators.pose([Validators.required,  emailValidator])],
      password: ['', Validators.required],
      confirmPassword: ['', Validators.required],
      firstName: ['', Validators.required],
      lastName: ['', Validators.required]
    }, {validator: matchingPasswords('password', 'confirmPassword')})

  }

  submitRegistration(value: Object): void {
    console.log(value);
  }

  veryOTPAsyn(otpControl: FormControl): Promise<any> {
    console.log(otpControl)
    console.log(otpControl.hasError('invalidOtp'))
    return new Promise<any>(
      (resolve, reject) => {
        setTimeout(() => {
          resolve({invalidOtp:true});
        }, 500);
      });
  }

}
Share Improve this question edited Jul 15, 2019 at 6:47 Kamil Naja 6,6926 gold badges37 silver badges52 bronze badges asked Jun 27, 2017 at 16:00 Saurabh PalatkarSaurabh Palatkar 3,38412 gold badges52 silver badges112 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 5

Try this :

 otp: ['', Validators.required, this.veryOTPAsyn.bind(this)]

Async validators go in 3rd argument

I would consider to remove the custom validation and instead set / remove error when user clicks on button instead, since the custom validators will run when ponent is initialized, as well as whenever input value changes. So have your click event, and do something like this (pseudo code):

(click)="veryOTPAsyn(registrationForm.controls.otp)"

and TS:

veryOTPAsyn(ctrl: FormControl) {
  if(ctrl.value == 'hey') {
    ctrl.setErrors({'invalidOtp':true})
  } else {
    ctrl.setErrors({'invalidOtp':null})
  }
}

Forked PLUNKER.


EDIT:

But if you want to go the route of using the async validator, just add the validator as third argument, but then you don't need the 'validate' button.

otp: ['', [Validators.required], [this.veryOTPAsyn]]

or do it like it's done now after the release of v 5.0.0

otp: ['', {validators: [Validators.required], asyncValidators: [this.veryOTPAsyn]}]

PLUNKER (pre v.5.0.0, so the first option of marking async validator is used)

发布评论

评论列表(0)

  1. 暂无评论