Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mark Form as Dirty (Manually) Without ngModel

Tags:

forms

angular

I'm using Angular 4.1.3 and came across this requirement and wanted to share my solution to it. Unfortunately the documentation on www.angular.io doesn't really list all the available props and methods on system components such as ngForm elements (or at least I couldn't find it).

My requirement was that I needed to have an <input> element that was part of a <form> that updated the value of its binding only after the blur event. Apparently this is only possible without using [ngModel] it seems:

<form #f="ngForm">
    <input (change)="myVar = $event.target.value" [value]="myVar" />
    <span *ngIf="f.dirty">Form is Dirty!</span>
</form>

But since this input isn't bound to an ngModel Angular doesn't know it's part of the form. So when the value is changed the form is not marked as dirty.

like image 452
Sal Avatar asked Aug 04 '17 14:08

Sal


People also ask

How do you make a form control dirty?

You should use the markAsDirty method, like this: control. markAsDirty(); This will also mark all direct ancestors as dirty to maintain the model.

What is mark as dirty in angular?

markAsDirty() is to mark all controls as dirty in the form. For this to work correctly, you'd have to also wrap it in a Clarity form container (which we don't have a generic wrapper yet, see #2864).

Can we use NgModel with FormControl?

NgModel works using these two bindings together. First, it passes the data from the component class and set data in FormControl. Second, it passes the data from UI after a specific action is triggered and then changes the value of the control.

What is difference between touched and dirty in angular?

The difference between touched and dirty is that with touched the user doesn't need to actually change the value of the input control. touched is true of the field has been touched by the user, otherwise it's false. The opposite of touched is the property untouched .


2 Answers

To solve this you need to manually set the form as dirty and to do that you can use the markAsDirty() method on the ngForm object like this:

<form #f="ngForm">
    <input (change)="myVar = $event.target.value; f.form.markAsDirty();" [value]="myVar" />
    <span *ngIf="f.dirty">Form is Dirty!</span>
</form>
like image 53
Sal Avatar answered Oct 23 '22 18:10

Sal


EDIT: Since using ngModel according to comment is not excluded, so as of angular 5 it's possible to use ngModel and add { updateOn: blur } and then check the form is dirty:

<form #f="ngForm" (ngSubmit)="logForm(f.value)">
  <label>Username</label>
  <input type="text" name="username" ngModel #userName="ngModel" [ngModelOptions]="{ updateOn: 'blur' }">
</form>

<p *ngIf="f.form.dirty">Form is Dirty!</p>

STACKBLITZ


ORIGINAL:

You need to register the form control with name attribute and ngModel. Now each control where you have marked an (unique) name value and ngModel means that it is now registered as a form control.

Furthermore you need to inspect the controls state by exporting ngModel to a local template variable, e.g like #someRef="ngModel". Now we can also do validations on this form control and at the same time, since Angular is following the state of this control, Angular can see that the form is dirty (among other things).

For example using the above we can have a (stripped down) form like this:

<form #f="ngForm">
  <label>Username</label>
  <input name="username" ngModel #userName="ngModel">
</form>

<span *ngIf="f.dirty">Form is Dirty!</span>
like image 2
AT82 Avatar answered Oct 23 '22 18:10

AT82