Triggering form validation programmatically in angular-js - javascript

I am using a custom directive to submit a form programmatically however no form validation is applied before submitting the form. I have called $setDirty() on the form field and $setSubmitted() on the form but the form is still submitted even if the required form field is empty.
directives/external.submit.js
export default class externalSubmit {
constructor ($timeout) {
'ngInject';
this.$timeout = $timeout;
this.restrict = 'A';
this.scope = {};
}
link($scope, $element, $attrs) {
$scope.$on('submit-form', function(event, data){
if( data.id === $attrs.id ) {
setTimeout(function() {
/**
* set form and fields to dirty
* this should be enabling validation
**/
var $formScope = angular.element($element).scope();
var $formController = $formScope[formName];
$formController.$setDirty();
$formController.$setSubmitted();
angular.forEach($formController.$error.required, function(field) {
field.$setDirty();
});
// trigger form submit
$element.triggerHandler('submit');
}, 0);
}
});
}
// Create an instance so that we can access this inside link
static factory() {
externalSubmit.instance = new externalSubmit();
return externalSubmit.instance;
}
};
foo/foo.controller.js
export default class FooController {
constructor( $rootScope ) {
'ngInject';
this.$rootScope = $rootScope;
this.item = {};
}
save() {
alert('Save triggered');
}
submitForm(id) {
// if no form id given, use the first form in the content area
if ( ! id ) id = $('form')[0].id;
this.$rootScope.$broadcast('submit-form',{'id':id} );
}
}
foo/foo.html
<form external-submit id="primary" ng-submit="$ctrl.save()" go-back="dashboard.home()">
<input type="hidden" ng-model="$ctrl.item.id"/>
<input required name="title" ng-model="$ctrl.item.title" type="text" />
<button type="submit">Internal Submit</button>
</form>
<button type="submit" ng-click="$ctrl.submitForm()">External Submit</button>

Use ng-submit="$valid && $ctrl.save()"

The solution is to check $formController to see if the form is valid before triggering the submit handler.
link($scope, $element, $attrs, $ctrl ) {
$scope.$on('submit-form', function(event, data){
if( data.id === $attrs.id ) {
let formName = $attrs.name;
setTimeout(function() {
// get the element scope
var $formScope = angular.element($element).scope();
// get the form controller using the form name
var $formController = $formScope[formName];
$formController.$setSubmitted();
// check if form is valid before triggering submit
if ( $formController.$valid ) {
$element.triggerHandler('submit');
}
// required to update form styles
$scope.$apply();
}, 0);
}
});
}

Related

ng-disable all input elements

Let's say I have 10 input elements on a page. I want to dynamically add ng-disabled to them based on the status of ng-model
For example:
<input type="text">
<input type="text">
I would not like to use a containing <fieldset></fieldset>.
Is this possible through something like a loop?
var allInputs = document.getElementsByTagName("input");
$scope.schoolClosed = true;
angular.forEach(allInputs, function(currentInput) {
currentInput.setAttribute("ng-disabled", "schoolClosed");
});
Which would yield results such as:
<input type="text" ng-disabled="schoolClosed">
<input type="text" ng-disabled="schoolClosed">
Can I add angular attribute elements through the dom like this?
Yes, you can. You can define a directive for the input element, which will get run for all inputs. Then you can have a service to store the disabled state, and "subscribe" to changes in your directive to set the disabled property directly without using ng-disabled.
I would imagine that you will need to make your service more complicated and maybe allow different named groups to toggle, rather than all or none. You could even specify the name of the group on a containing element or for each input.
You would also likely need to check in the directive whether it is a text input, so it doesn't get applied to every single radio button, checkbox, number input, etc in your application.
Full Plunkr example
var app = angular.module('plunker', []);
app.service('InputDisableService', function() {
this._isDisabled = false;
this._subscribers = [];
this.disabled = function(val) {
if (arguments.length < 1) {
return this._isDisabled;
}
var prev = !!this._isDisabled;
if (prev !== !!val) {
this._isDisabled = !!val;
for (var i = 0, len = this._subscribers.length; i < len; i++) {
this._subscribers[i].call(null, this._isDisabled, prev);
}
}
};
this.toggle = function() {
this.disabled(!this.disabled());
}
this.subscribe = function(callback) {
this._subscribers.push(callback);
// invoke immediately with current value, too
callback(this.disabled());
var self = this;
return {
unsubscribe: function() {
self.subscribers = self.subscribers.filter(function(sub) {
return sub !== callback;
});
}
};
};
});
app.directive('input', function(InputDisableService) {
return {
restrict: 'E',
link: function($scope, $element) {
var sub = InputDisableService.subscribe(function(disabled) {
$element.prop('disabled', disabled);
});
var off = $scope.$on('$destroy', function() {
sub.unsubscribe();
off();
});
}
}
});
app.controller('MainCtrl', function($scope, InputDisableService) {
$scope.inputs = [];
for (var i = 1; i <= 100; i++) {
$scope.inputs.push(i);
}
$scope.toggleDisabled = function() {
InputDisableService.toggle();
};
$scope.isDisabled = function() {
return InputDisableService.disabled();
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular.min.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
<p>Inputs disabled: {{isDisabled()}} Toggle</p>
<p ng-repeat="num in inputs">
<label>Input {{num}}
<input type="text">
</label>
</p>
</div>

AngularJS Directive Scope variables undefined

Here is the relevant JSFiddle
https://jsfiddle.net/9Ltyru6a/3/
In the fiddle, I have set up a controller and a directive that I want to use to call a callback whenever a value is change. I know that Angular has an ng-change directive, but I want something more akin to the standard onchange event (that gets triggered once when the field is blurred).
Controller:
var Controllers;
(function (Controllers) {
var MyCtrl = (function () {
function MyCtrl($scope) {
$scope.vm = this;
}
MyCtrl.prototype.callback = function (newValue) {
alert(newValue);
};
return MyCtrl;
})();
Controllers.MyCtrl = MyCtrl;
})(Controllers || (Controllers = {}));
Directive:
var Directives;
(function (Directives) {
function OnChange() {
var directive = {};
directive.restrict = "A";
directive.scope = {
onchange: '&'
};
directive.link = function (scope, elm) {
scope.$watch('onChange', function (nVal) {
elm.val(nVal);
});
elm.bind('blur', function () {
var currentValue = elm.val();
scope.$apply(function () {
scope.onchange({ newValue: currentValue });
});
});
};
return directive;
}
Directives.OnChange = OnChange;
})(Directives || (Directives = {}));
HTML:
<body ng-app="app" style="overflow: hidden;">
<div ng-controller="MyCtrl">
<button ng-click="vm.callback('Works')">Test</button>
<input onchange="vm.callback(newValue)"></input>
</div>
</body>
The button works, so I can safely say (I think) that the controller is fine. However, whenever I change the value of the input field and unfocus, I get a "vm is undefined" error.
Thanks for the help!
First of all, use proper controllerAs notation, not $scope.vm = this;:
ng-controller="MyCtrl as vm"
Then don't mix custom directive with native onchange event handler - this is the reason why you get undefined error. Name your directive something like onChange and use on-change attribute instead.
Correct code would look like:
var app = angular.module("app", []);
var Directives;
(function (Directives) {
function OnChange() {
var directive = {};
directive.restrict = "A";
directive.scope = {
onChange: '&'
};
directive.link = function (scope, elm) {
elm.bind('blur', function () {
var currentValue = elm.val();
scope.$apply(function () {
scope.onChange({
newValue: currentValue
});
});
});
};
return directive;
}
Directives.onChange = OnChange;
})(Directives || (Directives = {}));
app.directive("onChange", Directives.onChange);
var Controllers;
(function (Controllers) {
var MyCtrl = (function () {
function MyCtrl($scope) {
}
MyCtrl.prototype.callback = function (newValue) {
alert(newValue);
};
return MyCtrl;
})();
Controllers.MyCtrl = MyCtrl;
})(Controllers || (Controllers = {}));
app.controller("MyCtrl", ["$scope", function ($scope) {
return new Controllers.MyCtrl($scope);
}]);
Demo: https://jsfiddle.net/9Ltyru6a/5/
If the intent of your code is to only update your controller value on blur, rather than update it on every keypress, angular has ngModelOptions for this use. For example:
<input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'blur' }" />
you could even provide a debounce, or a button to clear the value....
<form name="userForm">
<input type="text" name="userName"
ng-model="user.name" ng-model-options="{ debounce: 1000 }" />
<button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button>
</form>
In these cases, if you were to supply an ng-change, it would only trigger on the blur event, or after the debounce.
You can also write directives that directly leverage the $validators or $asyncValidators from the ngModelController
here's an example from the Angular Developer Guide:
app.directive('username', function($q, $timeout) {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
var usernames = ['Jim', 'John', 'Jill', 'Jackie'];
ctrl.$asyncValidators.username = function(modelValue, viewValue) {
if (ctrl.$isEmpty(modelValue)) {
// consider empty model valid
return $q.when();
}
var def = $q.defer();
$timeout(function() {
// Mock a delayed response
if (usernames.indexOf(modelValue) === -1) {
// The username is available
def.resolve();
} else {
def.reject();
}
}, 2000);
return def.promise;
};
}
};
});
and the HTML:
<div>
Username:
<input type="text" ng-model="name" name="name" username />{{name}}<br />
<span ng-show="form.name.$pending.username">Checking if this name is available...</span>
<span ng-show="form.name.$error.username">This username is already taken!</span>
</div>
You could of course add the ng-model-options to ensure that this triggers only once.

show and hide bootsrap tooltip through javascript

I have a stuff which uses ui.bootsrap tool-tip feature, the code is working fine, but I don't know to show and hide the tooltip through script, say I am having a form which some field validation, when I submit the form, if the validation for a component say (a text field for email) fails, then it should shows up a tool-tip it should not go unless the field is properly validated,
Can anyone please tell me some solution for this
script
var app = angular.module('someApp', ['ui.bootstrap']);
app.controller('MainCtrl', function ($scope) {
$scope.validate = function () {
var re = /^([\w-]+(?:\.[\w-]+)*)#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
var emailValid = re.test($scope.userEmail);
if(!emailValid)
{
// I want to show the tool tip
}
};
})
html
<div ng-app="someApp" ng-controller="MainCtrl">
<form ng-submit="validate()">
<input type="text" ng-model='userEmail' rc-tooltip="Invalid Email...." tooltip-placement="bottom" />
<input type="submit" />
</form>
</div>
JSFiddle
Demo
Here is a simple email validation directive that uses bootstrap:
app.directive('email', function() {
return {
restrict: 'A',
require: 'ngModel',
compile: function(element, attr) {
element.tooltip({ placement: 'right', title:'Email is invalid', trigger:'manual'});
function emailValid(email) {
var re = /^([\w-]+(?:\.[\w-]+)*)#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
var valid = re.test(email);
return valid;
}
return function(scope, element,attr, ngModel) {
ngModel.$validators.email = function(val) {
return emailValid(val);
}
scope.$watch(function() {
return ngModel.$error.email;
}, function(val) {
if (val)
element.tooltip('show');
else
element.tooltip('hide');
});
}
}
}
});
Usage
<input type="text" ng-model="email" email />
Its given hereBootstrap Tooltip
And by using data-toggale option using javascript ,you can use tooltip.
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
By above code you can assign tooltip then to show and hide you can use
$('#element').tooltip('show')
or
$('#element').tooltip('hide')

how to pass values from localStorage to input field

I'm trying to pass localStorage to input field, but i'm not able to pass the values, i not getting where i'm going wrong, please help me with this, 1 thing more how can i call the angularjs function outside the controller. thanx for any help guys.
html
<div class="modal__content" ng-controller="joinctrl">
<form novalidate>
<input type="email" placeholder="Email" ng-model="email"><br />
<input type="password" placeholder="Password" ng-model="password"><br />
<input type="password" placeholder="Confirm Password" ng-model="cpassword"><br />
<input type="submit" value="Create" class="creat" ng-click="create()">
</form>
</div>
js
preauth();
function preauth() {
var user_login = window.localStorage.getItem('email');
var pass_login = window.localStorage.getItem('password');
if(user_login != undefined && pass_login != undefined) {
alert(user_login);
document.getElementById("email").value=user_login;
document.getElementById("password").value=pass_login;
angular.element(document.getElementById('loginctrl')).scope().Login();
}
}
var app = angular.module('contol', ['onsen']);
app.controller('loginctrl', function($scope, $http){
$scope.login=function(){
if (!$scope.email || !$scope.password){
alert("Please Fill Email & Password");
}
else{
var request=$http({
method:"post",
url:"http://www.example.com/login.php",
dataType: "json",
data:{
email:$scope.email,
password:$scope.password
},
headers:{'Content-Type':'application/x-www-form-urlencoded'}
});
request.success(function(retmsg){
if(parseInt(retmsg.status)==0)
{
alert(retmsg.txt);
}
else if (parseInt(retmsg.status)==1)
{
window.localStorage.setItem('email', $scope.email);
window.localStorage.setItem('password', $scope.password);
myNavigator.pushPage('home.html');
}
});
}
};
});
This may be useful,store it in variable and use it and only id name not #password
var x = document.getElementById("password").value = "Password";
alert ("The value was changed to: " + x);
In Angular applications, you should write ALL code inside modules. Otherwise, you don't use one of the useful feature of Angular: modularity.
For example:
app.factory("LocalStorage", function() {
var LS = {};
LS.getItem = function(key) {
return localStorage[key];
};
LS.setItem = function(key, value) {
localStorage[key] = value;
return value;
};
return LS;
});
app.controller('loginctrl', function($scope, $http, LocalStorage) {
$scope.email = LocalStorage.getItem('email');
$scope.password = LocalStorage.getItem('password');
$scope.login = function() {
// code...
// I'd rather to create another service "Api" or "Request", like this:
return Api.doAuth($scope.login, $scope.password).then(function(res) {
// For example, service `Request` write to `LocalStorage` status of current authentication.
if(res) {
myNavigator.pushPage('home.html');
}
});
};
});
You should not to call function in outside application (it's incorrect from the point of view Angular's philosophy). However, it's possible, you wrote right:
// get our scope:
var scope = angular.element(document.getElementById('loginctrl')).scope();
// and call our function in the scope:
scope.login();
But it's code you need to execute after Angular's bootstrap.
Also, you may to execute any function with Angular's services.
//find the `ng:app` element and get injector.
var injector = angular.element('body').injector();
//execute our own function with any services
injector.invoke(function($rootScope, $http, LocalStorage) {
$http.get('/foo.php').then(function(res) {
LocalStorage.setItem('answer', res);
});
$rootScope.bar = 1;
});

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