2

Is there anyway to Call method automatically like checkValidity() to set { 'invalid': false/true } after async form validation (i.e i have this.uniqueNameValidator.bind(this)) async call)

Checked https://stackoverflow.com/a/49520534/1225526 but it looks like submit method call after submit click action

Tried Form.valueChanges not work as expected it is called before validation

this.editForm.valueChanges
            .pipe(takeUntil(this._onDestroy))
            .subscribe(changes => {
                if (changes) {
                    this.onChange(Object.assign({userId: this.userId}, changes));
                }
                this.checkValidity(); <-- This part is not working as expected it is called before validation
            });



checkValidity() {
        if (((this.editForm.controls.userName.pristine && this.editForm.controls.userName.pending) ||
            !this.editForm.controls.userName.invalid)
            && !this.editForm.controls.password.invalid) {
            this.editForm.setErrors({ 'invalid': false });
        } else {
            this.editForm.setErrors({ 'invalid': true });
        }
    }

this.editForm = new FormGroup({
              userDisplayName: new FormControl({ value: '', disabled: true }),
              userName: new FormControl('', [ Validators.required], 
                       this.uniqueNameValidator.bind(this)), <-- async Validation
              password: new FormControl('',[Validators.required,
                       validateUserPassword()])});


uniqueNameValidator(control: AbstractControl) {
        return control.valueChanges.pipe(
            switchMap(() => this.service.checkUsernameAvailability(control.value)),
            take(1),
            map(({data}) => {
                control.markAsTouched();
                this.componentChangeDetector.markForCheck();
                return data.checkUsernameAvailability ? null : {invalid: false};
            }), catchError((error): any => {
                return of(null);
            }));
    }

Any help would be great.

Karthigeyan Vellasamy
  • 2,038
  • 6
  • 33
  • 50
  • you can do that at your async validator function. add a tap() to your pie and set parent form error sth like this : `tap(()=>control.parent.setErrors({'invalid':true}))...` – Eldar Nov 12 '19 at 09:25
  • I have a query. Why would you set your editForm errors. If any of the validation fails, editForm.valid returns true or false. Why would you explicitly call checkValidity and do so? – Saloo Nov 12 '19 at 09:27
  • I am using ControlValueAccessor as child form for writing other business data + form data which is instance of FormArray I need this child form to be validated manually since i am passing those FormControl to this child component for setting validation check so that i can iterate through this formArray from parent and enable submit button after checking their validity. Part of that form field is prefilled so it remains pending. – Karthigeyan Vellasamy Nov 12 '19 at 09:35

1 Answers1

3

AbstractControl provides two Observables valueChanges and statusChanges, maybe those can help you.

  • I used form statusChanges with setTimeout it worked. this.editForm.statusChanges.pipe(takeUntil(this._onDestroy)) .subscribe(status => this.checkValidity()); – Karthigeyan Vellasamy Nov 21 '19 at 05:41