AngularJS: integrating with server-side validation AngularJS: integrating with server-side validation angularjs angularjs

AngularJS: integrating with server-side validation


This is another case where a custom directive is your friend. You'll want to create a directive and inject $http or $resource into it to make a call back to the server while you're validating.

Some pseudo code for the custom directive:

app.directive('uniqueEmail', function($http) {  var toId;  return {    restrict: 'A',    require: 'ngModel',    link: function(scope, elem, attr, ctrl) {       //when the scope changes, check the email.      scope.$watch(attr.ngModel, function(value) {        // if there was a previous attempt, stop it.        if(toId) clearTimeout(toId);        // start a new attempt with a delay to keep it from        // getting too "chatty".        toId = setTimeout(function(){          // call to some API that returns { isValid: true } or { isValid: false }          $http.get('/Is/My/EmailValid?email=' + value).success(function(data) {              //set the validity of the field              ctrl.$setValidity('uniqueEmail', data.isValid);          });        }, 200);      })    }  }});

And here's how you'd use it in the mark up:

<input type="email" ng-model="userEmail" name="userEmail" required unique-email/><span ng-show="myFormName.userEmail.$error.uniqueEmail">Email is not unique.</span>

EDIT: a small explanation of what's happening above.

  1. When you update the value in the input, it updates the $scope.userEmail
  2. The directive has a $watch on $scope.userEmail it set up in it's linking function.
    • When the $watch is triggered it makes a call to the server via $http ajax call, passing the email
    • The server would check the email address and return a simple response like '{ isValid: true }
    • that response is used to $setValidity of the control.
  3. There is a in the markup with ng-show set to only show when the uniqueEmail validity state is false.

... to the user that means:

  1. Type the email.
  2. slight pause.
  3. "Email is not unique" message displays "real time" if the email isn't unique.

EDIT2: This is also allow you to use form.$invalid to disable your submit button.


I needed this in a few projects so I created a directive. Finally took a moment to put it up on GitHub for anyone who wants a drop-in solution.

https://github.com/webadvanced/ng-remote-validate

Features:

  • Drop in solution for Ajax validation of any text or password input

  • Works with Angulars build in validation and cab be accessed at formName.inputName.$error.ngRemoteValidate

  • Throttles server requests (default 400ms) and can be set with ng-remote-throttle="550"

  • Allows HTTP method definition (default POST) with ng-remote-method="GET"

Example usage for a change password form that requires the user to enter their current password as well as the new password.:

<h3>Change password</h3><form name="changePasswordForm">    <label for="currentPassword">Current</label>    <input type="password"            name="currentPassword"            placeholder="Current password"            ng-model="password.current"            ng-remote-validate="/customer/validpassword"            required>    <span ng-show="changePasswordForm.currentPassword.$error.required && changePasswordForm.confirmPassword.$dirty">        Required    </span>    <span ng-show="changePasswordForm.currentPassword.$error.ngRemoteValidate">        Incorrect current password. Please enter your current account password.    </span>    <label for="newPassword">New</label>    <input type="password"           name="newPassword"           placeholder="New password"           ng-model="password.new"           required>    <label for="confirmPassword">Confirm</label>    <input ng-disabled=""           type="password"           name="confirmPassword"           placeholder="Confirm password"           ng-model="password.confirm"           ng-match="password.new"           required>    <span ng-show="changePasswordForm.confirmPassword.$error.match">        New and confirm do not match    </span>    <div>        <button type="submit"                 ng-disabled="changePasswordForm.$invalid"                 ng-click="changePassword(password.new, changePasswordForm);reset();">            Change password        </button>    </div></form>


I have created plunker with solution that works perfect for me. It uses custom directive but on entire form and not on single field.

http://plnkr.co/edit/HnF90JOYaz47r8zaH5JY

I wouldn't recommend disabling submit button for server validation.