Getting server side validation in Angular shouldnt need to be difficult. Here we have a directive that can make our task very easy.

You shouldn’t need to change anything in your controllers, respond_with or returning json model.errors would do the trick.

First we will create our directive:


myApp.directive('serverError', function(){
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, element, attrs, ctrl){
      element.on('change', function(){
        scope.$apply(function(){
          ctrl.$setValidity('server', true);
        });
      });
    }
  }
});


Heres an example form that we will be validating. We have disabled HTML5 validations with the novalidate attribute on the form tag. We have added our directives attribute to the input.


<form name="form" ng-submit="save(model)" novalidate>
  <input type="text" name="username" ng-model="user.name" server-error />
  <div class="errors" ng-show="form.username.$dirty && form.username.$invalid">
    <span ng-show="form.username.$error.server">{{ errors.username }}</span>
  </div>
  <input type="submit" />
</form>

Now we need to add some things to our controller:


myApp.controller('UserCtrl', function($scope, UserService){
  $scope.save = function(user){
    $scope.errors = {}; // clean up server errors

    UserService.create(user)
      .then(function(result){
        // do stuff on success
      }, function(result){
        // Error function. Server will return something like: { errors: { username: ["Must be unique"] } }
        angular.forEach(result.data.errors, function(errors, field){
          // notify form that field is invalid
          $scope.form[field].$setValidity('server', false);
          
          // store the error messages from the server
          $scope.errors[field] = errors.join(', ');
        };
      });
  };
}

Now you have your server side errors working for you.

Note: This does not handle base errors.

** Thanks to Monterail team for this directive + setup


Related External Links: