Forms in AngularJS 1.3 have been improved quite a bit from what they were back in 1.2 and 1.1.
Lots of bugs for native HTML5 validators have been resolved and new features such as the validators
pipeline and asynchronous validations have also been introduced. Packaged together with nested forms
and the new ngMessages module, AngularJS 1.3 is more powerful than ever when it comes to developing
forms.

Let's have a look at these amazing new features and craft together some amazing user input forms!

Form validation in every framework is a different beast. With vanilla JavaScript it's even more
unpredictable. There has been some progress with the HTML5 form validation API, but overall, the API
is inconsistent and not all devices support it well enough and some platforms don't even support it
at all.

Thankfully AngularJS has made a versatile wrapper for this via ngModel. The internals of ngModel only
use the HTML5 validation API if needed, but overall the consistency between browsers is very good. And
with AngularJS 1.3 the level of control is much more advanced than with 1.2.

Not too long ago, back in June of 2014, at the Toronto AngularJS Meetup, I presented on form validation
with AngularJS and covered just about all of the topics here in this article. The video is visible
below via Youtube embed. Please keep in mind that, at the time of the presentation,
the asynchronous validation API was not stable yet.
So when the video itself is discussing how the API works for
promised-based validations, have a look at how they're done here in the article
afterwards. Otherwise, enjoy the video! I hope you laugh at my cheesy humour.

And there is also a companion demo repo that showcases all the features outlined in this article.
The links to the live demo and code repo can be found below...

It's is likely that everyone who has played with an Angular application has seen the ng-model
attribute that sits on HTML input elements. This magical directive bridges the gaps between the input
elements in the DOM world over to the scope and controller world. The bridge itself is called a two-way
data-binding and it effectively means that if the input field is updated by the user then the scope data
(the model value) will update. Then if the model value is updated then the DOM input value will also be
updated.

Now when the user enters a value into the input element the scope value will reflect what's in the input
field. When the button is clicked then the scope value changes first and the input field then reflects what
the scope value is.

The model value reflects the scope data which is tied to the input field. But the logic of passing values
back and forth between the DOM and the scope is all managed by a well constructed controller called
ngModelController. Each time an input element is tied together with the ng-model attribute then
the ngModel directive will create an instance of ngModelController and then all of the parsing, formatting,
validating and transporting of data will be handled by the controller.

The beauty of this setup is that we barely need any JavaScript code to handle standard things such as
passing data to the scope, performing validations and firing model-specific events. Have a look at the code
below:

The input element above is tied to a model value represented by the scope property myEmail. When
data is written by the user then the scope value will eventually be populated with the value. The input
element HTML code is also declaring a series of validation constrictions that must be met
_before_the value is written to scope by Angular.
The ngModelController in this case will check to see that the value is entered
by the user (required), the value has a minimum length of 5 (minlength) but also
a maximum length of 100 (maxlength) and that it also is an email field
(the email type attribute specifies this). These four validation
properties save us tons of JS code and allow us to use the same validators on other input elements within our
form code.

When a validator fails then it registers it's error on the instance of the ngModelController on the
$error object. However before we can display errors we need to first get ahold of the model within
the template. This can be achieved by first wrapping the model inside of a form and providing a
name value to both the form and the input element.

We can now examine the validation status of the model via myForm.myEmail.$error. We can also
examine other properties on the model such as $pristine, $dirty, $valid,
and $invalid. Having access to the model within the template allows for us to display error
messages whenever any of these values change.

<formname="myForm"><divclass="field"><inputtype="email"name="myEmail"minlength="5"maxlength="100"ng-model="myEmail"required /><divng-if="myForm.myEmail.$invalid">There is an error with the field...</div></div></form>

We can also gain access to the instance of the ngModelController within directive code where we can
place custom validations and create custom ngModel components. The trick to doing so is to include
the ngModel controller into our directive using require within our directive
definition block. The newly created directive must be placed on an element that also has ng-model on it.

Just like individual models, the containing form also has its own controller. The form controller is
designed to manage the validity of the entire form and it also has the $valid and $invalid
properties. The example below shows a controller that decides whether or not to submit the form data to
the backend depending on if the form status is valid.

The form template then calls the controller's submit method via the ng-submit attribute:

<formng-controller="FormCtrl as form"name="myForm"ng-submit="form.submit(myForm.$valid, data)"><divclass="field"><inputtype="email"name="myEmail"minlength="5"maxlength="100"ng-model="data.myEmail"required /><divng-if="myForm.myEmail.$invalid">There is an error with the field</div></div></form>

Notice how we used data as a collection to store the contents of the model? If we store
all of our model data within a single collection then the controller can trust that collection
data and send it off to the server. This pattern allows us to save a lot of JavaScript code.

Hopefully this intro shed some light on to the basics of ngModel. Let's continue to the next step
of the article and start to learn some of the cutting edge features of AngularJS 1.3!

Prior to AngularJS 1.3, only certain input attributes would trigger a validator to be registered
on the model. Now all of the HTML5 validation attributes are properly bound to ngModel and the errors
are registered on ngModel.$error whenever the validation fails. The table below shows
each of the attributes and what error will be triggered upon failure:

HTML5 Attribute

ng Attribute

Registered Error

required="bool"

ng-required="..."

ngModel.$error.required

minlength="number"

ng-minlength="number"

ngModel.$error.minlength

maxlength="number"

ng-maxlength="number"

ngModel.$error.maxlength

min="number"

ng-min="number"

ngModel.$error.min

max="number"

ng-max="number"

ngModel.$error.max

pattern="patternValue"

ng-pattern="patternValue"

ngModel.$error.pattern

The following input types are also automatically registered for validation:

Due to the nature of HTML5 form validation (the native DOM API), some input types may not expose
the input value (yes element.value) until the valid input value is entered into the field
by the user. This is the case for the number and each of the date input field types.

With 1.3, ngModel now does a consistent job of handling these situations by handling parse-related
validations first and then the rest of the validations. This means that if an invalid number, date,
url or email is entered then ngModel will display that error first before handling validators such
as required, minlength, max and so on.

AngularJS 1.3 uses $validators instead of $parsers + $formatters for performing validations.
This means that when it comes to creating custom validators, we must first create a directive and then include
ngModel in order to register the validator onto ngModel.$validators.
The code below shows an example of a password validator that checks to see if the input value matches
required range of characters for a password field.

<formname="myForm"><divclass="label"><inputname="myPassword"type="password"ng-model="data.password"validate-password-charactersrequired /><divng-if="myForm.myPassword.$error.required">
You did not enter a password
</div><divng-if="myForm.myPassword.$error.passwordCharacters">
Your password must contain a numeric, uppercase and lowercase as well as special characters
</div></div></form>

Now what about if we wanted to render an asynchronous validation? You something to like check to see
if the provided value is valid against the backend database? Can we just return a promise
inside of the validation function? Well if we use $asyncValidators then we can do just
that. Let's see how that's possible.

The $asyncValidators pipeline expects each of the validators to return a promise when a validation
is kicked off. When the promise fulfills itself then the validation is successful and when it rejects
then a validation error is registered. Only once all of the normal validators and the async validators
have successfully passed then the model value will be written to the scope.

One thing to keep in mind is that asynchronous validations will NOT run unless all of the prior
normal validators (the validators present inside of ngModel.$validators) have passed. This constriction
allows for the developer (yes you) to prevent the validator from making excessive backend calls
when the username input data is invalid. The example HTML code below explains this better:

<formname="myForm"><!--
first the required, pattern and minlength validators are executed
and then the asynchronous username validator is triggered...
--><inputtype="text"class="input"name="username"minlength="4"maxlength="15"ng-model="form.data.username"pattern="^[-\w]+$"username-available-validatorplaceholder="Choose a username for yourself"required /><!-- ... --></form>

Both the model and the form set the $valid and $invalid flags to undefined
once one or more asynchronous validators have been triggered and then, once everything has been resolved,
the $valid and $invalid flags will be restored based on the combined validity status of each of the asynchronous
validators. During this time a special object called $pending will be set on both the model and the
form to identify which asynchronous validations are ongoing. Once everything is complete then the pending
object will be removed.

Since the $pending object is set on the model this means that a loading animation can be placed
beside the model to indicate when the asynchronous operation (like the username HTTP request) is underway.

<formname="myForm"><!-- first the required, pattern and minlength validators are executed
and then the asynchronous username validator is triggered --><inputtype="text"name="myUsername"ng-model="data.username"minlength="10"pattern="^[-\w]+$"validate-username-availabilityrequired /><divng-if="myForm.myUsername.$pending">
Checking Username...
</div></form>

Whenever an input field is focussed on and then blurred the $touched property will be set to true.
Therefore if we place an ngIf or ngShow statement on a container surrounding the error messages then we can
control when they're displayed.

Now the form is a bit more user friendly. But what happens when we have too many errors? How can we control
the behaviour of what error messages show up and when? How can we setup a priority of which errors show up
first? AngularJS 1.3 also comes with support for this via a new module called ngMessages.

When the messages are displayed, only one message will show up at a time. The ng-messages
directive keeps track of the order of the error messages and it only renders the next message once
the error is gone from the model (the $error object). (Now keep in mind we're still using
the same ng-if code from before on the container element to control when the messages are
displayed.)

Also, before this code actually works, we need to download the angular-messages.js JavaScript
file and include ngMessages as a dependency for our application.

AngularJS 1.3 has a new feature called ngModelOptions which is basically an extra attribute that
allows for extra configurations to be applied to how ngModel works on the input element. One
particularly useful feature is something called value debouncing. This feature allows for
the input field to be configured to only update the model based on certain input events. The default
behaviour is that the input field will update ngModel each time the user types in a single character.

Let's say for example that we wanted to only perform asynchronous validations once all the validators
are passed in and the user has not typed in anymore characters for 500 milliseconds.

Now the validator won't be kicked off until things go quiet in terms of user input by half a second.
But can we extend this further? Can we make it so that the model value and validations are applied
immediately after when the user blurs out of the field? This can be handled by setting a wait time
of 0ms for the blur event.

ng-model-options="{ debounce : { 'default' : 500, blur : 0 } }"

Excellent stuff. This means that if there are any errors visible then they _will not evaluated_until
the debounce operation is over (this is after the timeout or when the user jumps out of the field).

Another super useful feature of deboucing with ngModelOptions is to control when the URL of page changes
due to a search querysting being applied when the user searches for something. Watch the video provided
above to see what I am talking about.

When ng-if was introduced it brought along the ability to add and remove subsections of forms
very easily. And by doing so new, optional, form input components can be added and removed and the
overall validity of the form would update according to the change of which fields are present and which
fields are not. Imagine if we built something like a calendar that collected an email address only if
the user wanted to provide an email address to by notified about the event. How would the HTML code look
like?

This may all seem trivial--and it is--but the key thing to pay attention to in the HTML code is that
the email input field will only show up when the checkbox is true. Yes this is still super basic, but
since the input field is being inserted and removed from the DOM whenever the checkbox model changes,
the validity of the input field will also be applied against the form. So in other words, when the
field is visible then it will render the form as invalid since the field is required, but when it is
removed then the form is valid again.

Let's now imagine that instead of having one email we wanted to have multiple. How can we change around
the HTML code allow for multiple emails to be collected and still make the validation of the form work
as normal? We can use ng-repeat inside and apply the data to the repeated item.

But what happens if the user enters an invalid email address? How can we show individual errors
for each repeated item? The trick here is to use nested forms via the ng-form attribute
on the element that is being repeated.

<divclass="field"ng-if="data.allowNotifications"><divng-form="emailForm"ng-repeat="email in notifcationEmails"><label>Email NaN:</label><inputtype="email"ng-model="email"name="notificationEmail" /><divng-if="emailForm.notificationEmail.$error.email">
You did not enter a valid email address
</div></div><buttonng-click="addAnotherEmail()">Add another email</button></div>

Awesome! But wait! Now there are wayyyy to many errors showing up. We can use ngMessages to clean things up
but is it possible to only show one error for all the repeated items together? If we place another ng-form
attribute, but on the container element, then we can certainly make it work.

<divclass="field"ng-if="data.allowNotifications"ng-form="notificationEmails"><divng-form="emailForm"ng-repeat="email in notifcationEmails"><label>Email NaN:</label><inputtype="email"ng-model="email"name="notificationEmail" /><divng-if="emailForm.notificationEmail.$error.email">
You did not enter a valid email address
</div></div><divng-if="notificationEmails.$error.email"class="error">
One or more emails have been incorrectly entered.
</div><buttonng-click="addAnotherEmail()">Add another email</button></div>

While parsers and formatters are not any different in AngularJS 1.3, the are not meant to handle any
validation logic. Instead, parsers are designed to convert the view value into a different model value
and formatters are for converting the model value into the appropriate view value. What's the difference
between the model value and the view value? The model value is what gets placed on the scope and the
view value is what exists within the DOM input element.

A good example of the use parsers in Angular is with how Angular internally handles date-based
input elements (like date, time, datetime, week, month, etc...).
What goes on here is the view value (entered by the user) is a string based value, but when it reaches the
scope the value itself is an instance of Date. The below is a simplified snippet of date parsing in action:

ngModel has been around since the start of AngularJS and the new features in 1.3 have definetly
improved upon the experience for both developers and users. Some of the new features may have a
tiny quirk or two. These kinks will be fixed in 1.3 stable, but now with the release of RC0 we
can be comfortable to use these new features since the API has been decided upon. So go ahead...
Don't be shy :)

If you happen to find any bugs or have any ideas in mind, please open a new issue on the AngularJS
repo on Github and, within your issue description, write the message to include @matsko
in the content. That way I will be able to see what you've typed :)

Thanks so much for reading all of this. If you don't mind, please share the article! And please
follow @yearofmoo on Twitter!