Search code examples
angularformsdirty-checking

How to make an Angular form field "clean" by re-typing original value?


In my code base using an Angular form, the user opens an entry to be edited and the various fields are pre-filled with the current values. The Save button starts disabled, because nothing isdirty in an Angular sense. If the user enters a field and starts typing, the field becomes dirty and the Save becomes enabled.

During the course of editing the form values, there are checks that disable the Save button if:

  • required fields are empty,
  • fields requiring a certain format have invalid entries,
  • entries are longer than permitted,

... and the like, and finally

  • the value, even if dirty, is now back to the original value when the user opened the form.

Here is the essence of it:

<!-- template code -->
<input formControlName="name" type="text" (keyup)="handleNameChange()">
. . .
<button [disabled]="!updateForm.valid || disableSave">Save</button>
. . .

// backing code
public handleNameChange(): void {
  this.disableSave = this.updateForm.controls.name.value === this.original.name;
}

Two questions:

A. Though it seems "obvious" from one perspective (nothing has changed so why should one have to save it?), is the last point a common, best practice in the UX sense? Would love to see articles or references about it.

B. Is there a way for an Angular form to do this (i.e. set a field back to non-dirty) automatically without my having to add explicit code to check the new value against the old value?


Solution

  • What you're wanting to do makes sense for a UI, although you might consider allowing the user to hit the button and display some sort of message alerting them that no changes had actually been made. Or if it's disabled, tell them why. Question A could probably be expanded on more over at UX StackExchange (Relevant question over there)

    As far as why Angular chooses to have the "dirty" state work as it does it more of a choice by them I supposed as the dirty state is triggered by any "change" event. It doesn't keep track of the original value as you already saw.

    A control is dirty if the user has changed the value in the UI. (Source)

    There's also information in the HTML5 input spec that talks about dirty fields

    Each input element has a boolean dirty value flag. The dirty value flag must be initially set to false when the element is created, and must be set to true whenever the user interacts with the control in a way that changes the value.

    This doesn't say anything about changing the value back to false/clean. So Angular might be following that.

    Unfortunately the answer to question B is no. You'll have to compare the values in some way and then use markAsPristine() or reset the form to do that or just have a separate manual check apart from using the "dirty" state.