Recently, I also talked to this, and I put out this demonstration . I think he does what you need.
Customize your form in accordance with the standards with any client-side checks you want to use:
<div ng-controller="MyCtrl"> <form name="myForm" onsubmit="return false;"> <div> <input type="text" placeholder="First name" name="firstName" ng-model="firstName" required="true" /> <span ng-show="myForm.firstName.$dirty && myForm.firstName.$error.required">You must enter a value here</span> <span ng-show="myForm.firstName.$error.serverMessage">{{myForm.firstName.$error.serverMessage}}</span> </div> <div> <input type="text" placeholder="Last name" name="lastName" ng-model="lastName"/> <span ng-show="myForm.lastName.$error.serverMessage">{{myForm.lastName.$error.serverMessage}}</span> </div> <button ng-click="submit()">Submit</button> </form> </div>
Note also that I added serverMessage for each field:
<span ng-show="myForm.firstName.$error.serverMessage">{{myForm.firstName.$error.serverMessage}}</span>
This is a custom message returned from the server, and it works just like any other error message (as far as I can tell).
Here is the controller:
function MyCtrl($scope, $parse) { var pretendThisIsOnTheServerAndCalledViaAjax = function(){ var fieldState = {firstName: 'VALID', lastName: 'VALID'}; var allowedNames = ['Bob', 'Jill', 'Murray', 'Sally']; if (allowedNames.indexOf($scope.firstName) == -1) fieldState.firstName = 'Allowed values are: ' + allowedNames.join(','); if ($scope.lastName == $scope.firstName) fieldState.lastName = 'Your last name must be different from your first name'; return fieldState; }; $scope.submit = function(){ var serverResponse = pretendThisIsOnTheServerAndCalledViaAjax(); for (var fieldName in serverResponse) { var message = serverResponse[fieldName]; var serverMessage = $parse('myForm.'+fieldName+'.$error.serverMessage'); if (message == 'VALID') { $scope.myForm.$setValidity(fieldName, true, $scope.myForm); serverMessage.assign($scope, undefined); } else { $scope.myForm.$setValidity(fieldName, false, $scope.myForm); serverMessage.assign($scope, serverResponse[fieldName]); } } }; }
I pretend that you are calling the server in pretendThisIsOnTheServerAndCalledViaAjax , you can replace it with an ajax call, period - this just returns the verification status for each field. In this simple case, I use the VALID value to indicate that the field is valid, any other value is treated as an error message. You may need something more complicated!
Once you have the validation status from the server, you just need to update the status in your form.
You can access the form from scope, in which case the form is called myForm , so $ scope.myForm gets the form. (The source for the form controller is here if you want to read how it works).
Then you want to tell the form whether the field is valid / invalid:
$scope.myForm.$setValidity(fieldName, true, $scope.myForm);
or
$scope.myForm.$setValidity(fieldName, false, $scope.myForm);
We also need to set an error message. First of all, access the field accessory using $ parse. Then assign the value from the server.
var serverMessage = $parse('myForm.'+fieldName+'.$error.serverMessage'); serverMessage.assign($scope, serverResponse[fieldName]);
Hope that helps