When I change a value in an input field, the corresponding form-control is set to dirty. When I revert my change (by typing in the input field) the form-control stays dirty. Is this intended, is this a bug or do I do something wrong?
Well, yes it's intended to work that way since:
A control is
dirty
if the user has changed the value in the UI. (docs entry)
..and not if the value is different from the starting value.
In case you want to revert the dirty state you could use the markAsPristine()
(docs entry) on your AbstractControl
. (eg trigger it by click on a button or when subscribing to the valueChanges
observable of the AbstractControl
and compare the new value to a previously stored one...)
markAsPristine()
for that –
Herzel user3725805
is correct -- that is touched. Otherwise, why is dirty
even there if after we rinse our glass and refill it our dishwasher thinks there's still backwash??? I'm sorry, this makes absolute nonsense. So the Angular team said, "Hey, let's come up with a totally hideous definition of what 'dirty' means so that nobody can tell if the form looks exactly like it did before any input". How can we tell if the form looks exactly as it did before input, then??????????????????? –
Zobkiw touched
indicates that a user visited the control, regardless of whether the value has changed. This is useful as a separate event from dirty since we may want to know when the user has blurred (touched) an input, even if the value is the same (e.g. to show an invalid state only after they've visited the input). If you want to know whether or not a control has been changed, store the original value, listen for changes on the input with valueChanges
, and compare the new value with the original. –
Selangor For a slightly different requirement, if we want to check if the input went back to empty (user deleted entry) after being dirty to not display the error message for ex, we will also face the same issue with "dirty" behavior.
In this case, as additional response to this post, I recommend creating a custom directive and apply it to all the inputs of the forms.
If input is empty and user click away after being dirty, we can apply the already mentioned markAsPristine() or markAsUntouched()
@Directive({
selector: '[noErrorOnEmpty]'
})
export class NoErrorOnEmptyDirective {
constructor(private control: NgControl) {}
@HostListener('blur')
onBlur() {
const control = this.control.control;
if (control?.value === '') {
control.markAsUntouched();
control.markAsPristine();
}
}
}
Then apply it on each of your inputs
<input
formControlName="username"
noErrorOnEmpty
--
OR
Add just add a function in your component
noErrorOnEmpty() {
Object.keys(this.userForm.controls).forEach(field => {
const control = this.userForm.get(field);
if (control?.value === '') {
control.markAsUntouched();
control.markAsPristine();
}
});
}
Then apply it on each of your inputs
<input
formControlName="username"
(blur)="noErrorOnEmpty()"
© 2022 - 2025 — McMap. All rights reserved.