Add custom validation to AngularJS form - javascript

In below form I'm checking that an e-mail address is required :
http://jsfiddle.net/U3pVM/16994/
I want to extend the validation so that it check that the first two characters begin with 'DD' . It seems I need to add a custom directive but I'm unsure how to link the e-mail fields with the directive ?
fiddle code :
<form ng-app="myApp" ng-controller="validateCtrl"
name="myForm" novalidate>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
</span>
</p>
<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
myForm.email.$dirty && myForm.email.$invalid">
</p>
</form>
var app = angular.module('myApp', []);
app.controller('validateCtrl', function($scope) {
});
app.directive("myValidator", function(){
// requires an isloated model
return {
// restrict to an attribute type.
restrict: 'A',
// element must have ng-model attribute.
require: 'ngModel',
link: function(scope, ele, attrs, ctrl){
// add a parser that will process each time the value is
// parsed into the model when the user updates it.
ctrl.$parsers.unshift(function(value) {
if(value){
// test and set the validity after update.
var valid = value.charAt(0) == 'D' && value.charAt(1) == 'D';
ctrl.$setValidity('invalidAiportCode', valid);
}
return valid ? value : undefined;
});
}
}
});

Here's how I would do it, using an authentication example:
The simple markup:
<input type="email" ng-model="existingUser.email">
<button ng-click="login(existingUser)">Login</button>
The controller:
auth.controller('AuthCtrl', '$scope', 'validation', function($scope, validation) {
$scope.existingUser = {
email: '',
password: ''
}
$scope.login = function() {
validation.validateSignin($scope.existingUser)
.catch(function(err) {
// The validation didn't go through,
// display the error to the user
$scope.status.message = err;
})
.then(function(res) {
// Validation passed
if (res === true) {
// Do something
}
});
}
}
The factory:
auth.factory('validation', ['$q', function($q) {
return {
validateSignin: function(existingUser) {
var q = $q.defer();
if (existingUser.email.substring(0,2) !== 'DD') {
q.reject('The email must start with "DD"');
}
q.resolve(true);
return q.promise;
}
}
}]);
Let me explain what's happening, first I'm creating a factory which will carry out the validation. Then I'm creating a promise with a resolve and a reject method, the reject method will be called if the validation failed, and if it succeeded then the resolve will be called. Then in your controller you can do things based on the outcome.
Let me know if anything is unclear.

Related

How to add custom validation to an angular component?

I have this angular component where I like to add a custom input validator (see plunker).
I'm trying to access the ngModelController in the $onInit function. But it seams that the form is not populated at this time. Later on in the sendEmail() function it's no problem to access the the input model controller. How can I access the ngModelController and add a custom validator?
emailInput.js
(function(angular) {
'use strict';
function EmailInputController($log) {
var ctrl = this;
ctrl.$onInit = function() {
// ctrl.myForm.myEmailInput is not populated
//$log.debug("Email view value is: "+(ctrl.myForm.myEmailInput.$viewValue));
};
ctrl.sendEmail = function() {
$log.debug("EmailInputController.sendEmail");
$log.debug("Email view value is: " + (ctrl.myForm.myEmailInput.$viewValue));
};
}
angular.module('emailInputApp').component('emailInput', {
templateUrl: 'emailInput.html',
controller: EmailInputController,
});
})(window.angular);
emailInput.html
<form name="$ctrl.myForm">
<label>Email:</label>
<input name="myEmailInput" type="email" ng-model="$ctrl.email" required maxlength="15">
<button type="button" ng-click="$ctrl.sendEmail()">Send Email</button>
<p>Your Email addres is {{$ctrl.email}}</p>
<div ng-messages="$ctrl.myForm.myEmailInput.$error" role="alert">
<div ng-message="required">Please enter an email address.</div>
<div ng-message="email">This field must be a valid email address.</div>
<div ng-message="maxlength">This field can be at most 15 characters long.</div>
</div>
<code>
{{$ctrl.myForm.myEmailInput | json}}
</code>
</form>
http://plnkr.co/edit/YQfGAsix1DON4ff3EWxz?p=preview
You can add watcher and remove it when not needed anymore.
var removeWatch = $scope.$watch('$ctrl.myForm', function () {
$log.debug("Email view value is: " + (ctrl.myForm.myEmailInput.$modelValue));
removeWatch();
});
app.directive('validateEmail', function() {
var EMAIL_REGEXP = /^[_a-z0-9]+(\.[_a-z0-9]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;
return {
require: 'ngModel',
restrict: '',
link: function(scope, elm, attrs, ctrl) {
// only apply the validator if ngModel is present and Angular has added the email validator
if (ctrl && ctrl.$validators.email) {
// this will overwrite the default Angular email validator
ctrl.$validators.email = function(modelValue) {
return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
};
}
}
};
});
And simply add
<input type='email' validate-email name='email' id='email' ng-model='email' required>

custom directive is not validating form. why not?

What code changes need to be made to get the custom countparens directive below to provide the extra custom string validation shown below during form validation? The code below DOES successfully alert the user when the input field is empty, but it IS NOT alerting the user when the number of open parens ( and close parens ) is not equal.
I am using AngularJS. I used the documentation at this link (scroll to bottom) to design the code below.
Here is the html for the form:
<table>
<tr>
<td width=200>
<form name="userForm" ng-submit="rectangularForm(userForm.$valid)" novalidate>
<input type="text" name="fieldname" ng-model="nameofjsontype.fieldname" required />
<p ng-show="userForm.fieldname.$invalid && !userForm.fieldname.$pristine" class="help-block">Function is a required field.</p>
<span ng-show="userForm.nameofjsontype.fieldname.$error.countparens">The #( != #) !</span>
<br>
<button type="submit" ng-disabled="userForm.$invalid" >Click to submit</button>
</form>
</td>
</tr>
</table>
The javascript file containing the directive includes:
// create angular app
var myApp = angular.module('myApp', []);
// create angular controller
myApp.controller('myController', ['$scope', '$http', function($scope, $http) {
$scope.nameofjsontype = {type:"nameofjsontype", fieldname: 'some (value) here.'};
$scope.rectangularForm = function(isValid) {
// check to make sure the form is completely valid
if (isValid) {
var funcJSON = {type:"nameofjsontype", fieldname: $scope.nameofjsontype.fieldname};
$http.post('/server/side/controller', funcJSON).then(function(response) {
$scope.nameofjsontype = response.data;
});
}
};
}]);
myApp.directive('countparens', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.countparens = function(modelValue, viewValue) {
if (ctrl.$isEmpty(modelValue)) {
// consider empty models to be valid
return true;
}
if (
($scope.nameofjsontype.fieldname.match(/\)/g).length) == ($scope.nameofjsontype.fieldname.match(/\(/g).length)
) {
// it is valid
return true;
}
// it is invalid
return false;
};
}
};
});
Your markup should be using userForm.fieldname.$error.countparens to show the error. The field bound to the userForm is NOT the same as your ngModel value. See plunker for what I mean
<span ng-show="userForm.fieldname.$error.countparens" class="help-block">The #( != #) !</span>
You are also not using your directive on your input element:
<input type="text" name="fieldname" ng-model="nameofjsontype.fieldname" required data-countparens=""/>
In your directive
you should be using modelValue and not the scope value when doing your matching AND
you need to cater for when there are no matches to ( or )
.
myApp.directive('countparens', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.countparens = function(modelValue, viewValue) {
return ctrl.$isEmpty(modelValue) ||
((modelValue.match(/\)/g) || []).length == (modelValue.match(/\(/g) || []).length);
};
}
};
});

Angular JS validation

I'm trying to validate my text area:
<form id="contact_form" name="contactform" ng-submit="submit(contactform)" role="form">
<textarea class="form-control" id="Message" ng-model="formData.message" ng-trim="false" placeholder="Your message" required="required" rows="8"></textarea>
</form>
For max word count, so I added a filter :
app.filter('wordCounter', function () {
return function (value) {
if (value && typeof value === 'string') {
return value.trim().split(/\s+/).length;
} else {
return 0;
}
};
});
And when this filter is met I print out an error :
<span class="help-block" ng-show="(formData.message|wordCounter) > 200">
Max 200 words please!
</span>
But still when I check in my controller contactform.$valid is always true, how do I make form invalid if the filter wordcounter is more than 200?
You need to create a custom validation directive. With Angular 1.3 $validators it's very easy.
For example, simple one:
.directive('maxWords', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
ngModelController.$validators.maxWords = function(viewValue, modelValue) {
if (!ngModelController.$isEmpty(modelValue)) {
return modelValue.trim().split(/\s+/).length <= attrs.maxWords;
}
};
}
};
});
Demo: http://jsfiddle.net/m3pp71o4/

Custom directive for telephone format using angularjs

I am trying to write custom directive for USA telephone number using angularjs and need to preserve the data type of the field as integer.Here is the jsfiddle directive and need help to complete the directive.
If user enters a valid telephone no (exactly 10 numbers ie.1234567890) then input should split into 3 chunks as 123-456-7890 when the user moves to next control.otherewise I should show error message "not a valid number".
<div ng-app="myApp" ng-controller="myCtrl">
<form name="myForm">
<input type="text" ng-model="telephone" phoneformat name="input1" />
<span class="error" ng-show="myForm.input1.$error.telephone">Numbers only!</span>
<span class="error" ng-show="myForm.input1.$error.telephone">Exact 10 Numbers only!</span>
</form>
</div>
var myApp = angular.module("myApp", []);
var myCtrl = myApp.controller("myCtrl",["$scope", function($scope) {
$scope.telephone = "1234567890";
}]);
myApp.directive("phoneformat", function () {
return {
restrict: "A",
require: "ngModel",
link: function (scope, element, attr, ngModelCtrl) {
var phoneformat = function () {
}
}
};
});
It looks like you want to leverage the $error property of the form to drive validation. To do this, you will need to call $setValidity in the ngModelCtrl that you have required into your directive:
var myApp = angular.module("myApp", []);
var myCtrl = myApp.controller("myCtrl",["$scope", function($scope) {
$scope.telephone = "1234567890";
}]);
myApp.directive("phoneformat", function () {
return {
restrict: "A",
require: "ngModel",
link: function (scope, element, attr, ngModelCtrl) {
//Parsing is performed from angular from view to model (e.g. update input box)
//Sounds like you just want the number without the hyphens, so take them out with replace
var phoneParse = function (value) {
var numbers = value && value.replace(/-/g, "");
if (/^\d{10}$/.test(numbers)) {
return numbers;
}
return undefined;
}
//Formatting is done from view to model (e.g. when you set $scope.telephone)
//Function to insert hyphens if 10 digits were entered.
var phoneFormat = function (value) {
var numbers = value && value.replace(/-/g,"");
var matches = numbers && numbers.match(/^(\d{3})(\d{3})(\d{4})$/);
if (matches) {
return matches[1] + "-" + matches[2] + "-" + matches[3];
}
return undefined;
}
//Add these functions to the formatter and parser pipelines
ngModelCtrl.$parsers.push(phoneParse);
ngModelCtrl.$formatters.push(phoneFormat);
//Since you want to update the error message on blur, call $setValidity on blur
element.bind("blur", function () {
var value = phoneFormat(element.val());
var isValid = !!value;
if (isValid) {
ngModelCtrl.$setViewValue(value);
ngModelCtrl.$render();
}
ngModelCtrl.$setValidity("telephone", isValid);
//call scope.$apply() since blur event happens "outside of angular"
scope.$apply();
});
}
};
});
Working fiddle. This was just a quick way of demonstrating the parser and formatter pipelines that are used in ngModel, along with $setValidity -- which is used to populate the $error field(s).
Update: To use this same phone validation across multiple phones, use form with $error. Notice that each input gets a unique name that is used with myForm (name of form). Both use $error.telephone:
<form name="myForm">
Mobile Phone:
<input type="text" ng-model="mobilephone" phoneformat name="mobilephone" />
<span class="error" ng-show="myForm.mobilephone.$error.telephone">
Exact 10 Numbers only!
</span>
<br />
Home Phone:
<input type="text" ng-model="homephone" phoneformat name="homephone" />
<span class="error" ng-show="myForm.homephone.$error.telephone">
Exact 10 Numbers only!
</span>
</form>
Updated fiddle.
You might want to use http://angular-ui.github.io/ui-utils/ Mask directive.
Working Fiddle: http://jsfiddle.net/HB7LU/6581/
myApp.directive("phoneFormat", function () {
return {
restrict: "A",
link: function (scope, element, attr) {
element.bind('change', function() {
if ( this.value.length === 10 ) {
var number = this.value;
this.value = number.substring(0,3) + '-' + number.substring(3,6) + '-' + number.substring(6,10)
}
else {
document.querySelector('.helpblock').innerHTML = 'error in formatting';
}
});
}
};
});
Iv'e extended your original fiddle. here's the result:
http://jsfiddle.net/10k58awt/
You can find splittedNumber array (contains 3 parts of number) on form submission
js:
var myApp = angular.module("myApp", []);
var myCtrl = myApp.controller("myCtrl", ["$scope", function ($scope) {
$scope.telephone = "1234567890";
$scope.submit = function () {
var splittedNumber = [$scope.telephone.substring(0, 3), $scope.telephone.substring(3, 6), $scope.telephone.substring(6, 10)];
// Do something with splitted number
console.log(splittedNumber);
};
}]);
myApp.directive("phoneformat", function () {
return {
restrict: "A",
require: "ngModel",
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (phoneInput) {
phoneInput = phoneInput.trim();
if (phoneInput && phoneInput.length == 10 && !isNaN(phoneInput)) {
ctrl.$setValidity('phoneformat', true);
return phoneInput;
} else {
ctrl.$setValidity('phoneformat', false);
return undefined;
}
});
}
};
});
html:
<div ng-app="myApp" ng-controller="myCtrl">
<form name="myForm" novalidate ng-submit="myForm.$valid && submit()">
<input type="text" ng-model="telephone" phoneformat name="input1" /> <span class="error" ng-show="myForm.input1.$error.phoneformat">Invalid US Phone number!</span>
<div>
<button class="btn btn-primary" type="submit" ng-class="{'disabled': !myForm.$valid}">submit</button>
</div>
</form>
</div>

AngularJS custom form validation using $http

I have a form that looks like this:
<form name="myForm" ng-submit="saveDeployment()">
<input type="hidden" value="{{item.CloneUrl}}" name="cloneurl" />
<input type="hidden" value="{{Username}}" name="username" />
<input type="radio" name="deploymenttype" ng-model="item.deploymentType" value="azure" checked="checked">Azure
<br />
<input type="radio" name="deploymenttype" ng-model="item.deploymentType" value="ftp">FTP
<div id="azure" ng-show="item.deploymentType=='azure'">
<label for="azurerepo">Azure Git Repo</label>
<input type="text" name="azurerepo" ng-model="item.azurerepo" ng-class="{error: myForm.azurerepo.$invalid}" ng-required="item.deploymentType=='azure'" />
</div>
<div id="ftp" ng-show="item.deploymentType=='ftp'">
<label for="ftpserver">FTP Server</label>
<input type="text" name="ftpserver" ng-model="item.ftpserver" ng-class="{error: myForm.ftpserver.$invalid}" ng-required="item.deploymentType=='ftp'" />
<label for="ftppath">FTP Path</label>
<input type="text" name="ftppath" ng-model="item.ftppath" ng-class="{error: myForm.ftppath.$invalid}" ng-required="item.deploymentType=='ftp'" />
<label for="ftpusername">FTP Username</label>
<input type="text" name="ftpusername" ng-model="item.ftpusername" ng-class="{error: myForm.ftpusername.$invalid}" ng-required="item.deploymentType=='ftp'"/>
<label for="ftppassword">FTP Password</label>
<input type="password" name="ftppassword" ng-model="item.ftppassword" ng-class="{error: myForm.ftppassword.$invalid}" ng-required="item.deploymentType=='ftp'"/>
</div>
<input type="submit" value="Save" ng-disabled="myForm.$invalid"/>
</form>
Its setup so that the required fields and Save button are all working once data is entered. However, part of my validation will be, "Is the user already registered?" where I will use the data entered to hit the server via POST using $http.
Should I put that logic in the saveDeployment() function or is there a better place to put it?
*UPDATE:*
I've implemented the below which is applied as an attribute on a element but it calls the server/database on every key press which I don't like:
app.directive('repoAvailable', function ($http, $timeout) { // available
return {
require: 'ngModel',
link: function (scope, elem, attr, ctrl) {
console.log(ctrl);
ctrl.$parsers.push(function (viewValue) {
// set it to true here, otherwise it will not
// clear out when previous validators fail.
ctrl.$setValidity('repoAvailable', true);
if (ctrl.$valid) {
// set it to false here, because if we need to check
// the validity of the email, it's invalid until the
// AJAX responds.
ctrl.$setValidity('checkingRepo', false);
// now do your thing, chicken wing.
if (viewValue !== "" && typeof viewValue !== "undefined") {
$http.post('http://localhost:12008/alreadyregistered',viewValue) //set to 'Test.json' for it to return true.
.success(function (data, status, headers, config) {
ctrl.$setValidity('repoAvailable', true);
ctrl.$setValidity('checkingRepo', true);
})
.error(function (data, status, headers, config) {
ctrl.$setValidity('repoAvailable', false);
ctrl.$setValidity('checkingRepo', true);
});
} else {
ctrl.$setValidity('repoAvailable', false);
ctrl.$setValidity('checkingRepo', true);
}
}
return viewValue;
});
}
};
});
You don't need to make $http request in directive, better place for it is controller.
You can specify method inside controller - $scope.saveDeployment = function () { // here you make and handle your error on request ... }; you'll save error to scope and then create a directive that will watch $scope.yourResponseObject and set validity based on it.
Also if you need something like request and error on input field blur instead, you need to create a simple directive with elem.bind('blur', ...) where you call $scope.saveDeployment with callback to handle validity.
Take a look on the examples, there might be something similar - https://github.com/angular/angular.js/wiki/JsFiddle-Examples
Validating a form input field using an asynchronous $http ajax call is a common need, but I haven't found any implementations that were complete, reusable, and easy to use so I tried my best to make one.
This functionality is especially useful for checking if a username, email, or other field/column is unique, but there are plenty of other use cases where a value must be validated with an ajax call (as in your example).
My solution has the following features:
Accepts a "check" function from the $scope that makes the $http call or any kind of validation (synchronous or asynchronous)
Accepts a "gate" function from the $scope that allows the check to be bypassed based on the value or ngModel state.
Debounces the "check" function's execution until the user has stopped typing
Ensure that only the latest $http call result is used (in case multiple are fired and return out of order).
Allows for state bindings so that the UI can respond appropriately and conveniently.
Customizable debounce time, check/gate functions, binding names and validation name.
My directive is pmkr-validate-custom (GitHub). It can be used for any asynchronous validation. I've tested it in several versions as far back as 1.1.5.
Here is a sample usage with Twitter Bootstrap in which I check if a username is unique.
Live Demo
<form name="the_form" class="form-group has-feedback">
<div ng-class="{'has-success':userNameUnique.valid, 'has-warning':userNameUnique.invalid}">
<label for="user_name">Username</label>
<input
name="user_name"
ng-model="user.userName"
pmkr-validate-custom="{name:'unique', fn:checkUserNameUnique, gate:gateUserNameUnique, wait:500, props:'userNameUnique'}"
pmkr-pristine-original=""
class="form-control"
>
<span ng-show="userNameUnique.valid" class="glyphicon glyphicon-ok form-control-feedback"></span>
<span ng-show="userNameUnique.invalid" class="glyphicon glyphicon-warning-sign form-control-feedback"></span>
<i ng-show="userNameUnique.pending" class="glyphicon glyphicon-refresh fa-spin form-control-feedback"></i>
<p ng-show="userNameUnique.valid" class="alert alert-success">"{{userNameUnique.checkedValue}}" is availiable.</p>
<p ng-show="userNameUnique.invalid" class="alert alert-warning">"{{userNameUnique.checkedValue}}" is not availiable.</p>
<button
ng-disabled="the_form.$invalid || the_form.user_name.$pristine || userNameUnique.pending"
class="btn btn-default"
>Submit</button>
</div>
</form>
Sample controller:
// Note that this ought to be in a service and referenced to $scope. This is just for demonstration.
$scope.checkUserNameUnique = function(value) {
return $http.get(validationUrl+value).then(function(resp) {
// use resp to determine if value valid
return isValid; // true or false
});
}
// The directive is gated off when this function returns true.
$scope.gateUserNameUnique = function(value, $ngModel) {
return !value || $ngModel.$pristine;
};
If I make any improvements, they will be up-to-date on GitHub, but I am also going to put the code here for this directive and its dependencies (may not be updated). I welcome suggestions or issues though GitHub issues!
angular.module('pmkr.validateCustom', [
'pmkr.debounce'
])
.directive('pmkrValidateCustom', [
'$q',
'pmkr.debounce',
function($q, debounce) {
var directive = {
restrict: 'A',
require: 'ngModel',
// set priority so that other directives can change ngModel state ($pristine, etc) before gate function
priority: 1,
link: function($scope, $element, $attrs, $ngModel) {
var opts = $scope.$eval($attrs.pmkrValidateCustom);
// this reference is used as a convenience for $scope[opts.props]
var props = {
pending : false,
validating : false,
checkedValue : null,
valid : null,
invalid : null
};
// if opts.props is set, assign props to $scope
opts.props && ($scope[opts.props] = props);
// debounce validation function
var debouncedFn = debounce(validate, opts.wait);
var latestFn = debounce.latest(debouncedFn);
// initially valid
$ngModel.$setValidity(opts.name, true);
// track gated state
var gate;
$scope.$watch(function() {
return $ngModel.$viewValue;
}, valueChange);
// set model validity and props based on gated state
function setValidity(isValid) {
$ngModel.$setValidity(opts.name, isValid);
if (gate) {
props.valid = props.invalid = null;
} else {
props.valid = !(props.invalid = !isValid);
}
}
function validate(val) {
if (gate) { return; }
props.validating = true;
return opts.fn(val);
}
function valueChange(val) {
if (opts.gate && (gate = opts.gate(val, $ngModel))) {
props.pending = props.validating = false;
setValidity(true);
return;
}
props.pending = true;
props.valid = props.invalid = null;
latestFn(val).then(function(isValid) {
if (gate) { return; }
props.checkedValue = val;
setValidity(isValid);
props.pending = props.validating = false;
});
}
} // link
}; // directive
return directive;
}
])
;
angular.module('pmkr.debounce', [])
.factory('pmkr.debounce', [
'$timeout',
'$q',
function($timeout, $q) {
var service = function() {
return debounceFactory.apply(this, arguments);
};
service.immediate = function() {
return debounceImmediateFactory.apply(this, arguments);
};
service.latest = function() {
return debounceLatestFactory.apply(this, arguments);
};
function debounceFactory(fn, wait) {
var timeoutPromise;
function debounced() {
var deferred = $q.defer();
var context = this;
var args = arguments;
$timeout.cancel(timeoutPromise);
timeoutPromise = $timeout(function() {
deferred.resolve(fn.apply(context, args));
}, wait);
return deferred.promise;
}
return debounced;
}
function debounceImmediateFactory(fn, wait) {
var timeoutPromise;
function debounced() {
var deferred = $q.defer();
var context = this;
var args = arguments;
if (!timeoutPromise) {
deferred.resolve(fn.apply(context, args));
// return here?
}
$timeout.cancel(timeoutPromise);
timeoutPromise = $timeout(function() {
timeoutPromise = null;
}, wait);
return deferred.promise;
}
return debounced;
}
function debounceLatestFactory(fn) {
var latestArgs;
function debounced() {
var args = latestArgs = JSON.stringify(arguments);
var deferred = $q.defer();
fn.apply(this, arguments).then(function(res) {
if (latestArgs === args) {
deferred.resolve(res);
}
}, function(res) {
if (latestArgs === args) {
deferred.reject(res);
}
});
return deferred.promise;
}
return debounced;
}
return service;
}
])
;
angular.module('pmkr.pristineOriginal', [])
.directive('pmkrPristineOriginal', [
function() {
var directive = {
restrict : 'A',
require : 'ngModel',
link: function($scope, $element, $atts, $ngModel) {
var pristineVal = null;
$scope.$watch(function() {
return $ngModel.$viewValue;
}, function(val) {
// set pristineVal to newVal the first time this function runs
if (pristineVal === null) {
pristineVal = $ngModel.$isEmpty(val) ? '' : val.toString();
}
// newVal is the original value - set input to pristine state
if (pristineVal === val) {
$ngModel.$setPristine();
}
});
}
};
return directive;
}
])
;
My solution was taken from Kosmetika's idea.
I used the angular-ui project and set an onBlur callback that was on the controller which called the web service via $http.
This set a controller/model property to true or false.
I then had a <span> use ng-show to watch the controller/model property so when the web service returned it would show the user information

Categories

Resources