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.
You should use the markAsDirty method, like this: control. markAsDirty(); This will also mark all direct ancestors as dirty to maintain the model.
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).
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.
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 .
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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With