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


1 answer


I thought! Was dealing with a throttled resource ... obviously setting debounceMS to 0 was not enough to prevent it from doing the debouncing part. I switched to $ resource and everything worked (but that also means the deboucing part for onValueChanged won't work).



+1


source







All Articles