I've hacked a solution to my problem, but I am not pleased, it doesn't feel "angular" to me, and it adds to the maintenance of the code.
First, the form requirements:
The problem is #3. I tried this:
<div ng-show="myform.$valid">
<input type="submit" value="Submit" />
</div>
But this just makes the submit button show up as soon as one field is valid, and then it hides again as you start the next field. My "hack fix" was to create variables on the scope and a method in the controller to check them all (mainly to keep the view clean...) But this just doesn't feel right.
Here's my fiddle: http://jsfiddle.net/thomporter/e3jye/
I was just poking around with this and here's what I landed on for highlighting errors on an email field in logical order (using bootstrap form control groups)... http://jsfiddle.net/kNKbJ/1/
<form name="form" ng-app>
<div class="control-group" ng-class="{true: 'error'}[form.email.$error.email || (submitted && form.email.$error.required)]">
<label class="control-label" for="email">Your email address</label>
<div class="controls">
<input type="email" name="email" ng-model="email" required />
<span class="help-inline" ng-show="submitted && form.email.$error.required">Required</span>
<span class="help-inline" ng-show="form.email.$error.email">Invalid email</span>
</div>
</div>
<button type="submit" class="btn btn-primary btn-large" ng-click="submitted=true">Submit</button>
</form>
You could add the submitted check to anything you don't want to show until after first submit
It's a common problem that people don't want all of their validation messages showing at the same time, even if they all apply.
The following form should fit your requirements, however I didn't "Bootstrap theme" the error validation messages. It is only using the default angular functionality.
But in a nutshell, it should show the required message, if a value exists but it's not a valid email, it should show the invalid email message.
It also hides the submit button if it's not valid... HOWEVER... I recommend just disabling the submit button with ng-disabled instead. It's poor usability IMO to not let people know where the submit button is.
<form name="myForm">
<label for="email">Email</label>
<input type="email" id="email" name="email" ng-model="formData.email" required/>
<span ng-show="myForm.email.$error.required && myForm.email.$dirty">required</span>
<span ng-show="!myForm.email.$error.required && myForm.email.$error.email && myForm.email.$dirty">invalid email</span>
<button type="submit" class="btn" ng-show="myForm.$valid">Submit</button>
</form>
It gets a little long adding those checks to the validation, but it is the "angular way" to do it.
I hope that helps.
I wanted to add another solution to this and make it as complete as possible. This validation has a similar look & feel to asp.net's validation summary control.
The form loads from JSON. The form fields and validation are pulled from a function called requiredFields. Validation doesn't show up until you've clicked the button, instead of being in your face on load.
Here's a bit of the relevant code:
HTML
<div ng-show="showValidation() && !formReset">
<h4>The following errors were found:</h4>
<ul ng-repeat="(key,val) in requiredFields()">
<li ng-show="myForm[key].$invalid">{{val}} is required</li>
</ul>
</div>
<form name="myForm" novalidate>
<label>Age: <span class="ng-cloak" ng-show="myForm.age.$valid">✔</span></label>
<input type="number" name="age" ng-model="form.age" required />
<button ng-click="clickButton()">Submit</button>
</form>
JS
$scope.clickButton = function() {
$scope.formReset = false;
$scope.showValidation = function () { return $scope.myForm.$invalid; }
if ($scope.myForm.$valid)
$scope.jsonoutput = JSON.stringify($scope.form);
}
Full code: http://plnkr.co/edit/GAHHab7pEFtlyHnPWVux?p=preview
novalidate" in the form tag is important if you don't want the pop up tooltip showing up. From my understanding, the 'required' attribute is part of HTML5 and is conflicting with angularjs' required directive.