question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Forms: State that setErrors() will make status === INVALID regardless of value passed for key

See original GitHub issue

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

In the setErrors example for AbstractControl it shows passing true for the key. The issue is that the control’s status will be set to INVALID no matter the value of the key (or even just passing setErrors an empty object (see _calculateStatus code) However, as the example is given, it’s reasonable to infer that you clear the errors by setErrors( {"notUnique": false}), when really you’d need to do setErrors(null) or, as the example does show, set the control’s value to a new value.

const login = new FormControl("someLogin");
login.setErrors({
  "notUnique": true
});

expect(login.valid).toEqual(false);
expect(login.errors).toEqual({"notUnique": true});

login.setValue("someOtherLogin");

expect(login.valid).toEqual(true);

Expected behavior

Update documentation to explicitly say how to clear errors in code (as this is useful to know when doing integration (template) testing, where you just want to set an error, check the template, then clear the error and check that any alerts have gone away.

Minimal reproduction of the problem with instructions

Failing test

const login = new FormControl("someLogin");
login.setErrors({
  "notUnique": true
});

expect(login.valid).toEqual(false);
expect(login.errors).toEqual({"notUnique": true});

login.setErrors({"notUnique": false});
expect(login.valid).toEqual(true); //will still be INVALID since the check: if(this.errors) will return TRUE

Suggested example

const login = new FormControl("someLogin");
login.setErrors({
  "notUnique": true
});

expect(login.valid).toEqual(false);
expect(login.errors).toEqual({"notUnique": true});

login.setValue("someOtherLogin"); //or: login.setErrors(null); <===add this comment

expect(login.valid).toEqual(true);

Alternatively (though this would be code change, not just a documentation change), is that in _calculateStatus(), you only set to INVALID if at least one key in the errors object is set to true.

What is the motivation / use case for changing the behavior?

When I am doing integration (template) testing to validate that alert/error messages show up when a control is invalid, and I choose to use the setErrors() function to create an INVALID status, I want to know how to then create a VALID status (either by setting a valid value or by passing null to the control.setErrors() function.

Environment


Angular version: 4.4.1


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:17
  • Comments:30 (9 by maintainers)

github_iconTop GitHub Comments

35reactions
KostaMadorskycommented, Apr 7, 2019

I am using the following Utils methods to handle adding and removing errors from controls:

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


  public static addErrors(errors: { [key: string]: any }, control: AbstractControl) {
    if (!control || !errors) {
      return;
    }

    control.setErrors({ ...control.errors, ...errors });
  }
16reactions
jbmikkcommented, Jun 25, 2018

I have come across the same problem in a different scenario.

I am using custom errors to set errors returned from the server on specific inputs. Only the server knows how to validate the values and the only feedback I get from the server comes in the error response after I POST something, so I can’t validate the values before attempting to POST. So when the server returns a status 400 I parse the response, I see which inputs have failed and then call setErrors on the inputs as appropiate.

After the user makes changes to the form I want to clear these errors, but if I call setErrors with null I’m also clearing other errors added by the validators I already have on some of the inputs.

I only want to remove the errors I added, not all the errors on that input. I think being able to add custom errors but not being able to remove them easily is not very useful.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Invalidate form control with setErrors - angular - Stack Overflow
I'm trying to add an error to a form control (without any validators) and expect an invalid state ...
Read more >
Understanding Angular Reactive Forms | by Leonardo Giroto
A Form Control is a class which holds the value and validation status of each propertie of your form. Roughly, each 'input' in...
Read more >
FormGroup - Angular
Tracks the value and validity state of a group of FormControl instances. ... When instantiating a FormGroup , pass in a collection of...
Read more >
FormGroup - Angular
You reset to a specific form state by passing in a map of states that matches the structure of your form, with control...
Read more >
Class Entity | CakePHP 4.1
Returns an array that can be used to describe the internal state of this object. __get() public. Magic getter to access fields that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found