Forms can be quite tedious in angular, mostly having to do with messages. There's several options: highight the invalid fields or show messages, show messages only when dirty, disable submit button, etc. I don't like the disabled submit button as it leaves the user guessing which field is invalid, and... if they're not guessing which field is invalid, then all invalid fields or messages are "always" shown, I don't care for that as well. My solution this time around was to show messages only when dirty, leaving the submit button enabled, then setting all fields to dirty upon submission. So, no messages shown until the submit button is hit or they visit the field Upon submit all messages are shown for invalid fields. This feels right.
Also, played around a bit with ng-module-options.updateOn and have to say, blur isn't cool. You just can't wait for a blur event for error message updates or even field updates (a select won't change it's value after you select an option until you blur away). The ux felt more responsive using the "default" option, so just let the default ride (updates on every key hit).
I have to say, I had my doubts when I first ran through the docs and examples on the ngMessages module, but working on this example has turned me around. I found it much cleaner and much more resuable to use the ngMessages module. Surely the global messages alone make it worthwhile. The ng-messages expression is a bit of a mystery. I.e. it's looking for an object hash, but will take booleans too. Not sure how far that can be pushed, but surely there's code that's looking for booleans and disregarding them in the hash it's gonna use. Was nice to see it allowed and followed boolean additions. That made all the difference as I was wondering how to limit the messages to dirty only.
I'm not a big fan of these, but this example turned out better than I'd have thought. The main problem was multiple messages for the same field. I.e. how to know which one is causing the issue. Case in point "required" on the email control, and the field shows invalid after you start typing as it rolls from required to invalid email errors. I tossed in a message for the latter, which seemed appropriate enough, i.e. maybe the solution is to augment style changes with messages. Also, the setting dirty trick didn't work with classes as the form.field.$dirty setting didn't set the ng-dirty class. Also, the trick I saw on the web: setting form.field.$setViewValue(form.field.$viewValue) didn't set it to dirty either (as stated it would). There's not form.field.$setDirty(), but there is form.field.$setTouched, so I ran with ng-touched instead and all worked fine.
formEmbeddedMessages.html:
allow them to hit submit button, old-style embedded messages
formNgMessages.html:
same deal, but using a global message template and the new ngMessages module
formClasses.html: uses classes to set a red outline on invalid fields (instead of messages), yet augments the email control with a message to discern between a required error and an invalid email error.
messages.html:
global message template