Custom angularJS validator to check unique user name using $http service

In previous post Custom validator for AngularJS applications I described how to write custom validators. In this post I will show how to write a custom validator that checks validity by sending asynchronous request to server.

Check availability of username

In this discussion I will develop a validator that will be used to check if a user name is available when a user is signing up or registering. This implementation shows development of a custom service that is injected in the validator.

Custom AngularJS server


    TradePortalApp.factory('accounts', ['$q', '$http', '$log', function ($q, $http, $log) {
    var checkUserName = function (name) {
        var action = PortalSettings.baseUrl + "api/TradeIdentity/UserNameAvailable";
        return $http(
            { method: 'POST', url: action, params: { userName: name } })
            .then(
            function (result) {
                return { code: 200, found: result.data == "true" }
            }, function (result) {
                return { code: 500, found: null }
            });
    }
    return {
        checkUserName: checkUserName
    };
}]);

This custom service accounts uses $http service to send asynchronous request to server to check if the specific user name is available or not. Since this request is asynchronous, the method returns a promise to the caller. When $http request completes, it returns the results to caller's promise completion function.

Custom AngularJS validation directive

Following code shows implementation of tradeUniqueUserName custom validator that will check if user name is unique or not.


    TradePortalApp.directive('tradeUniqueUserName', ['accounts', function (accounts) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            if (!ctrl) return;
            elm.bind('blur', function () {
                scope.$apply(checkUserName);
            });
            var checkUserName = function () {
                var userName = elm.val();
                accounts.checkUserName(userName).then(function (result) {
                    if (result.code == 200) {
                        ctrl.$setValidity('tradeUniqueUserName', !result.found);
                    }
                });
                return userName;
            };
        }
    };
}]);
TradePortalApp.controller("TradeRegistrationController", 
     ['$scope', 'accounts', function ($scope, accounts) {
    $scope.registration = { UserName: '', Email: '' };
}]);

This custom validator does not inject itself into NgModelController's $parser collection. Instead it registers onblur event handler on HTML element. This will prevent validation to be triggered for every single character being entered in text box. By registering for blur event handler, this validtator will only trigger when text box looses focus.

Prototype

Following HTML code snippet shows how this all is used to put all the pieces together to build a user registration sign up page.


<div class="row">
 <div class="col-sm-offset-3 col-xs-6">
 <div class="page-header"><h2>Sign up as trader</h2></div>
 <div class="row">
 <div ng-controller="TradeRegistrationController">
 <form name="registrationForm" role="form" novalidate>
 <div class="form-group">
  <label>User name</label>
  <input type="text" name="userName" maxlength="50" ng-model="registration.UserName" 
       trade-unique-user-name ng-model-options="{updateOn: 'blur'}" 
       class="form-control" />
  <span class="field-validity-error" 
      ng-show="registrationForm.userName.$error.tradeUniqueUserName">This user name is not available</span>
 </div>
 <div class="form-group">
  <label>Email</label>
  <input type="email" ng-model="registeration.Email" class="form-control" />
 </div>
<div>
<button type="submit" class="btn btn-primary">Register</button>
 </div>
 </form>
 </div>
 /div>
</div>
</div>

Following image shows result of this validator.

You can click here to see all this in live action. Currently MVC WebApi sends true or false randomly. You can type some text in user name text box and then focus away from this text box to see how validation error shows after validating user name from server.

comments powered by Disqus

Blog Tags