angularjs: custom directive to check if a username exists
there is a great tutorial by yearofmoo about $asyncvalidators in angular1.3. it allows you to easily show pending status when the field is being checked by the backend:
here's a working plnkr
app.directive('usernameAvailable', function($timeout, $q) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, model) {
model.$asyncValidators.usernameExists = function() {
//here you should access the backend, to check if username exists
//and return a promise
//here we're using $q and $timeout to mimic a backend call
//that will resolve after 1 sec
var defer = $q.defer();
$timeout(function(){
model.$setValidity('usernameExists', false);
defer.resolve;
}, 1000);
return defer.promise;
};
}
}
});
html:
<form name="myForm">
<input type="text"
name="username"
ng-model="username"
username-available
required
ng-model-options="{ updateOn: 'blur' }">
<div ng-if="myForm.$pending.usernameExists">checking....</div>
<div ng-if="myForm.$error.usernameExists">username exists already</div>
</form>
note the use of ng-model-options, another cool feature of 1.3
edit
here's a plnkr that shows how to use $http in the directive. note that it is only requesting another .json file, that contains a true/false value. and the directive will set validity on the ng-model accordingly.
Lee Lee
Updated on July 09, 2022Comments
-
Lee Lee almost 2 years
I have my registration form with textbox username. I want to do is when the user enter the username, the custom directive will check if the entered username is exists in the database.
directives.js
angular.module('installApp').directive('pwCheck', function ($http) { return { require: 'ngModel', link: function (scope, elem, attrs, ctrl) { elem.on('blur', function (evt) { scope.$apply(function () { $http({ method: 'GET', url: '../api/v1/users', data: { username:elem.val(), dbField:attrs.ngUnique } }).success(function(data, status, headers, config) { ctrl.$setValidity('unique', data.status); }); }); }); } } });
If it's exists, my
div class = "invalid"
will shown in the html form with label "Username already exists."registration.html
<form name = "signupform"> <label>{{label.username}}</label> <input type="text" id = "username" name = "username" ng-model="user.username" class="form-control"></input> <div class="invalid" ng-show="signupform.username.$dirty && signupform.username.$invalid"><span ng-show="signupform.username.$error.unique">Username already exists.</span> </div> </form>
But right now, they are not working :-(,am I doing right? Please advice or suggest me things I should do. Thanks in advance.
-
Lee Lee over 9 yearsThat is great @Nitsan Baleli. I am new to directives may I ask you another question, can you help me how to access my backend? I tried the plunker and no matter what I enter it always said that the user is already exists. I know I need to add some code but I do not know how to access my backend via directives and compare them. Thanks a lot in advance
-
Lee Lee over 9 yearshi there. I saw the updated answer and fork it :-). I put some values inside the backend.json. I entered them one by one and it's okay its display "user already exists" but when I enter a value which is not listed in the .json it still displays "user already exists", am I missing something? Thank you again, Here is the link plnkr.co/edit/2kIjx46buEinjpWx9rpR?p=preview
-
Nitsan Baleli over 9 years@Yaoming keep in mind that setting the model as valid/invalid is made with this command: model.$setValidity('usernameExists', res.data); so what ever the backend gives you, you need to decide and set the appropriate true/false value on the model.
-
Lee Lee over 9 yearsHello is this correct ` return $http.get('../api/v1/users').then(function(res)`?
-
Lee Lee over 9 yearsOkay let's chat. . Where do you want?
-
Lee Lee over 9 yearsSorry if I am too much. . But I need your help, what should I do to access my backend?
-
Nitsan Baleli over 9 yearsLet us continue this discussion in chat.
-
Lee Lee over 9 yearsThank you Nitsan Baleli. Your code now is working in my project, I just changed some process but it works fine. Thank you a lot. :-)
-
Eka Rudianto almost 9 yearsHi @NitsanBaleli I've tried your method, but it seems the ngModel value didn't get updated, did I missed something ?
-
Nitsan Baleli almost 9 years@user3860691 try this approach plnkr.co/edit/QrI9Y9W72ejCKZXq1I3v?p=preview
-
Eon almost 8 yearsbit late - due to bug github.com/angular/angular.js/issues/10035 you might want to set
$q.defer();
to a variable, and manually have$q.resolve()
fired when the validation passes - otherwise it still destroys a value within your scope.