Angularjs only last asynchronous call in actually executed directive
Note. I am using AngularJS 1.2
I have a form where each field is sent to the server to check for a changed value.
Below is the html snippet (assuming the html is set up correctly for all purposes):
<div class="col-sm-5">
<input class="form-control input-sm" url="type:googleplus" ng-model="element.googleplus" type="text"><br />
<input class="form-control input-sm" url="type:yelp" ng-model="element.yelp" type="text"><br />
<input class="form-control input-sm" url="type:foursquare" ng-model="element.foursquare" type="text>
</div>
In my javascript, I have set a directive that intercepts each field and tries to hit the server as the value is updated. The scenario that breaks the current functionality is when the form is loaded with populated values.
OnValueChanged calls Validate.Options multiple times with no pause in between. I expected the server to be removed for every Validation.Options request, but instead only the last call is made .
AngularJS below:
...
.factory('Validation', ['va', function (va) { // 'va' is a throttled resource
var result = va('/manage/api/validate?type=:type&input=:url',
{
type: '@type',
url: '@url'
},
{
options: {
method: 'options',
debounceMS: 0, // turned off debounce in lieu of this problem
abortPending: false
}
});
return result;
}])
...
.directive('url', ['$filter', 'Validation', '$q', function ($filter, Validation, $q) {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
// parses some stuff
var config = {};
(attrs['url'] || '').split(' ').map(function (p) { var a = p.split(':'); config[a[0]] = a[1]; });
if (config.type)
config.type = config.type.split(',');
config.isRequired = elm[0].required;
function validateUrl(viewValue, type) {
var deferred = $q.defer();
Validation.options({ url: viewValue, type: type }, function (response) {
deferred.resolve(response.IsValid);
});
return deferred.promise;
}
function onValueChanged(viewValue) {
// hits the server to check if the url is valid
if (viewValue) {
var type = config.type ? config.type[0] : undefined;
validateUrl(viewValue, type).then(function (isValid) {
ctrl.$setValidity('url', isValid);
});
}
else {
// prevents saving the listing as field is invalid
ctrl.$setValidity('url', !config.isRequired);
}
return viewValue;
}
ctrl.$parsers.push(onValueChanged);
// revalidate when the model updates
scope.$watch(
function () { return ctrl.$viewValue; },
function (viewValue) { return onValueChanged(viewValue); }
);
}
};
}])
Why should only the last call be executed? When I open the network tab, I see exactly one server call of type "foursquare".
+3
source to share