phacic
phacic

Reputation: 1542

Angular Abstract control remove error

I want a way to remove a specific error from a form control and not clear all error.

control.setError({'firstError': true})

and to remove that specific error like

control.removeError({'firstError}) and not control.setError({null})

I tried

control.setError({'firstError': false})

but didn't work.

Any help. Thanks

angular 4.1.1

Upvotes: 62

Views: 88772

Answers (12)

Amir Azizkhani
Amir Azizkhani

Reputation: 1804

for clear all validations you can use markAsUntouched function like below. for example for form group controls:

for (let controlsKey in this.formGroup.controls) {
      let control = this.formGroup.controls[controlsKey];
      control.markAsUntouched();
}

Upvotes: 4

CharanRoot
CharanRoot

Reputation: 6325

You can remove like this:

control.setErrors({'firstError': null})

Upvotes: 33

GeeWhizBang
GeeWhizBang

Reputation: 857

I was having this bug caused by using *ngIf to show some controls. I want to delete ALL errors and start from scratch this works:

Object.keys(this.myForm.controls).forEach(controlName => {
  if (controlName != "search") {
    let control = that.myForm.controls[controlName];
    if (control.errors) {
      let errorKeys = Object.keys(control.errors);
      errorKeys.forEach(key => {
        delete control.errors[key];
      })
    }
    control.setErrors(null);
    this.options[controlName + "Error"] = null;
  }
});

in my code I want to leave the "search" control alone, and I also clear the error strings I save in this.options.{controlName}Error

Upvotes: 0

MDave
MDave

Reputation: 1365

control.setErrors({'firstError': null});

Will not working anymore. You need to use a helper method. Copied from https://github.com/angular/angular/issues/21564#issuecomment-480569715

public static removeErrors(keys: string[], control: AbstractControl) {
  if (!control || !keys || keys.length === 0) {
    return;
  }

  const remainingErrors = keys.reduce((errors, key) => {
    delete errors[key];
    return errors;
  }, { ...control.errors });

  control.setErrors(remainingErrors);

  if (Object.keys(control.errors || {}).length === 0) {
    control.setErrors(null);
  }
}

Upvotes: 4

Alessandro
Alessandro

Reputation: 353

this.form.controls["field"].setErrors(null);

Upvotes: 1

Swapnil Mahadik
Swapnil Mahadik

Reputation: 696

You can remove error with:

control.setErrors({'firstError': null});

control.updateValueAndValidity();

Upvotes: 58

Aamer Shahzad
Aamer Shahzad

Reputation: 2947

I am using Dynamic Forms and I wanted to clear the error of one component from another. I tried .setErrors() method but it was not working. The working solution for me is listed below.

clearControlError( control: AbstractControl ): void {
    const err = control.errors;
    if (err) {
        delete err['timeNotValid'];
        if (!Object.keys(err).length) {
            control.setErrors(null);
        } else {
            control.setErrors(err);
        }
    }
}

now I can clear error of any AbstractControl type control by passing it to the function like this.

this.clearControlError(this.formBase.parent.get('startTime'));

or

this.clearControlError(this.form.controls['startTime']);

Upvotes: 5

slzr
slzr

Reputation: 101

I came from this github issue and try this little workaround 😬

Using Destructuring assignment

if ( control.hasError('errorToRemove') ) {
  const { errorToRemove, ...errors } = control.errors;
  control.setErrors(errors);
  control.updateValueAndValidity();
}

You can also try the omit or pick lodash functions, to respectively omit or pick a series of errors that you can set to the control later.

const errors = pick(control.errors, ['onlyErrorsToKeep']);
control.setErrors(errors);
control.updateValueAndValidity();
const errors = omit(control.errors, ['allErrorsToRemove']);
control.setErrors(errors);
control.updateValueAndValidity();

Upvotes: 9

Dschuli
Dschuli

Reputation: 379

Much has already been stated in other posts to this question (e.g. delete the error property (which still leaves the control flagged as invalid), issues with updateValueAndValidity() in changeHandlers (infinite loop) etc). Putting it all together I now use the below small function, which leaves other errors untouched and resets the invalid flag if no other errors remain:

removeFormControlError(control: AbstractControl, errorName: string) {
  if (control?.errors && control?.errors[errorName]) {
    delete control.errors[errorName];
    if (Object.keys(control.errors).length === 0) {
      control.setErrors(null);
    }
  }
}

Upvotes: 17

jkyoutsey
jkyoutsey

Reputation: 2041

If we are dynamically adding and removing errors, as of Angular 8, the above examples simply don't work. I'm adding errors based upon the state of other controls. i.e. I have two customers defined with the same email address. This is the only solution I could find that actually works.

tap(duplicateError => {
    /* Note to future self...
     * I'm beginning to hate AbstractControl.errors.
     * The email control can have multiple errors (required, email, and duplicate);
     * The ONLY way to clear an error is to not have it in the object that is passed to the setErrors call.
     * You CANNOT pass null or undefined! It will still be evaluated as an error!
     * This is also true if there are NO errors AT ALL. You cannot pass setErrors({}) or the control will be
     * invalid, even though there are no errors! You must call setErrors(null);
     * This is stupid, but it's the only way it works.
     * This code is concerned with setting/removing the duplicate error.
     */
    const email = this.form.get('email');
    // Clone the existing errors
    const existingErrors = { ...email.errors };
    // Ensure that duplicate error is removed (we're in the change handler for the duplicate error)
    delete existingErrors.duplicate;
    if (duplicateError) {
        // We have a new duplicate error, so add it.
        email.setErrors({ ...existingErrors, duplicate: duplicateError.errorMessage });
    } else if (Object.keys(existingErrors).length === 0) {
        // We have NO errors, so pass null
        email.setErrors(null);
    } else {
        // We have existing errors, but no new duplicate error. Pass the existing errors.
        email.setErrors(existingErrors);
    }
    this.changeDetector.markForCheck();
})

Upvotes: 3

Denis Anisimov
Denis Anisimov

Reputation: 865

First, you should check your field for has this error. next, remove it. And for end you are need to update all errors in your controll.

Something like this in validator function:

if (control.hasError('firstError')) {
      delete control.errors['firstError'];
      control.updateValueAndValidity();
    }

Regards.

Upvotes: 51

Ram_T
Ram_T

Reputation: 8484

Unfortunately, it didn't work for me. I simply used updateValueAndValidity() which is used to re-calculate the value and validation. The below is my validator function which validates my grossWeight.

validateWeights(formGroup) {
    let netWeight = formGroup.get('netWeight');
    let grossWeight = formGroup.get('grossWeight');

    if (parseFloat(netWeight.value) > parseFloat(grossWeight.value)) {
        grossWeight.setErrors({ 'customError': true });
        netWeight.setErrors({ 'customError': true });
    } else {
        if(netWeight.errors && netWeight.errors['customError']) {
            netWeight.updateValueAndValidity();
        }
        if (grossWeight.errors && grossWeight.errors['customError']) {
            grossWeight.updateValueAndValidity();
        }
    } 
}

Upvotes: 5

Related Questions