Created
July 3, 2013 03:19
-
-
Save wvuong/5915184 to your computer and use it in GitHub Desktop.
Example of custom validation for an account registration form via directives. Note: the validateUnique directive's expression expects a promise because the server-side uniqueness check is asynchronous.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('registerapp.controllers', ['registerapp.services']). | |
controller('RegisterFormController', ['$scope', '$window', '$location', 'UsernameService', '$q', function($scope, $window, $location, UsernameService, $q) { | |
$scope.user = {}; | |
$scope.checkUsername = function() { | |
if ($scope.user.username) { | |
return UsernameService.checkForDuplicateUsername($scope.user.username); | |
} | |
}; | |
$scope.submitForm = function() { | |
$http.post(contextPath + '/register', $scope.user) | |
.success(function(data, status) { | |
$location.path('/done'); | |
}) | |
.error(function(data, status) { | |
$window.alert('account registration unsuccessful, error code ' + status); | |
}); | |
}; | |
}]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('common.directives', []). | |
directive('validateUnique', function() { | |
return { | |
restrict: 'A', // only activate on element attribute | |
require: 'ngModel', // get a hold of NgModelController, | |
link: function(scope, element, attrs, ngModel) { | |
if(!ngModel) return; // do nothing if no ng-model | |
// attach listener to watch model value for change and revalidate every change | |
element.on('keyup', function() { | |
scope.$apply(function() { | |
// eval the expression in the validate-unique attribute | |
var promise = scope.$eval(attrs.validateUnique); | |
if (promise) { | |
promise.then(function(result) { | |
if (result === true) { | |
ngModel.$setValidity('unique', false); | |
} | |
else { | |
ngModel.$setValidity('unique', true); | |
} | |
}); | |
} | |
}); | |
}); | |
} | |
}; | |
}). | |
directive('validateSameValueAs', function() { | |
return { | |
restrict: 'A', | |
require: 'ngModel', | |
link: function(scope, element, attrs, ngModel) { | |
// get reference input element | |
var reference = angular.element('#' + attrs.validateSameValueAs); | |
if (!reference) { | |
return; | |
} | |
// update validity on key input | |
element.on('keyup', function() { | |
scope.$apply(function() { | |
if (reference.val() === element.val()) { | |
ngModel.$setValidity('samevalue', true); | |
} | |
else { | |
ngModel.$setValidity('samevalue', false); | |
} | |
}); | |
}); | |
// update validity if reference input changes | |
reference.on('keyup', function() { | |
scope.$apply(function() { | |
if (reference.val() === element.val()) { | |
ngModel.$setValidity('samevalue', true); | |
} | |
else { | |
ngModel.$setValidity('samevalue', false); | |
} | |
}); | |
}); | |
} | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div ng-controller="RegisterFormController"> | |
<form name="registerForm" class="form-register" novalidate ng-submit="submitForm()"> | |
<h2 class="form-signin-heading">Register New Account</h2> | |
<div class="control-group" ng-class="{error: registerForm.username.$invalid}"> | |
<label class="control-label" for="username">Name</label> | |
<div class="controls"> | |
<input type="text" id="username" name="username" placeholder="Username" ng-model="user.username" | |
validate-unique="checkUsername(user.username)" | |
ng-minlength="4" | |
ng-maxlength="12" | |
ng-pattern=/^\w*$/ required> | |
<span class="help-inline" ng-show="registerForm.username.$valid"><i class="icon-ok"></i> Username OK!</span> | |
<span class="help-block" ng-show="registerForm.username.$error.required && registerForm.username.$dirty"><i class="icon-warning-sign"></i> Required</span> | |
<span class="help-block" ng-show="registerForm.username.$error.pattern"><i class="icon-warning-sign"></i> Must be only alphanumeric characters, no spaces</span> | |
<span class="help-block" ng-show="registerForm.username.$error.unique"><i class="icon-warning-sign"></i> Username is already taken</span> | |
<span class="help-block" ng-show="registerForm.username.$error.minlength"><i class="icon-warning-sign"></i> Username must be at least 4 characters</span> | |
<span class="help-block" ng-show="registerForm.username.$error.maxlength"><i class="icon-warning-sign"></i> Username must be at most 12 characters</span> | |
</div> | |
</div> | |
<div class="control-group" ng-class="{error: registerForm.email.$invalid}"> | |
<label class="control-label" for="email">Email Address</label> | |
<div class="controls"> | |
<input type="email" id="email" name="email" placeholder="Email address" ng-model="user.email" required> | |
<span class="help-inline" ng-show="registerForm.email.$valid"><i class="icon-ok"></i> Email OK!</span> | |
<span class="help-block" class="error" ng-show="registerForm.email.$dirty && registerForm.email.$error.required"><i class="icon-warning-sign"></i> Required</span> | |
<span class="help-block" class="error" ng-show="registerForm.email.$dirty && registerForm.email.$invalid"><i class="icon-warning-sign"></i> Invalid email address</span> | |
</div> | |
</div> | |
<div class="control-group" ng-class="{error: registerForm.password.$invalid || registerForm.password2.$invalid}"> | |
<label class="control-label" for="password">Password</label> | |
<div class="controls"> | |
<input type="password" id="password" name="password" placeholder="Password" ng-model="user.password" required> | |
<span class="help-inline" ng-show="registerForm.password.$valid"><i class="icon-ok"></i> Password OK!</span> | |
<span class="help-block" class="error" ng-show="registerForm.password.$dirty && registerForm.password.$error.required"><i class="icon-warning-sign"></i> Required</span> | |
</div> | |
<label class="control-label" for="password2">Reenter Password</label> | |
<div class="controls"> | |
<input type="password" id="password2" name="password2" placeholder="Password" | |
ng-model="secondPassword" | |
validate-same-value-as="password" | |
required> | |
<span class="help-inline" ng-show="registerForm.password2.$valid"><i class="icon-ok"></i> Passwords match OK!</span> | |
<span class="help-block" class="error" ng-show="registerForm.password2.$dirty && registerForm.password2.$error.required"><i class="icon-warning-sign"></i> Required</span> | |
<span class="help-block" class="error" ng-show="registerForm.password2.$dirty && registerForm.password2.$error.samevalue"><i class="icon-warning-sign"></i> Passwords do not match.</span> | |
</div> | |
</div> | |
<div class="form-actions"> | |
<button class="btn btn-large btn-primary" type="submit" ng-disabled="registerForm.$invalid">Register Account</button> | |
</div> | |
</form> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('registerapp.services', ['common.filters']). | |
factory('UsernameService', ['$filter', '$http', '$log', '$q', function($filter, $http, $log, $q) { | |
var fn = $filter('relativeUrl'); | |
return { | |
checkForDuplicateUsername : function(value) { | |
var deferred = $q.defer(); | |
$http({ | |
url: fn('/register/check'), | |
method: 'GET', | |
params: {username: value} | |
}) | |
.success(function(data) { // json data returned by server has an exists property | |
deferred.resolve(data.exists === true); | |
}) | |
.error(function() { | |
deferred.reject(); | |
}); | |
return deferred.promise; | |
} | |
}; | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment