Tommaso Sebastianelli
Tommaso Sebastianelli

Reputation: 193

AngularJS watcher not binding/ watching

I'm trying to implement the "infinite-scroll" feature in a list using a directive, which should load progressively a new set of "orders" when the scroll of the html element reaches or exceeds 75% of the scrollable height and append it to the existing list. Unfortunately, the watcher doesn't trigger when i scroll the list. The directive is located in the right tag and the watcher triggers the listener function only the first time, when the element is rendered by the browser. The strange thing is that if i change path and then i return to the path where the list is, the watcher start behaving correctly and trigger the listener function everytime i perform a scroll.

<ol orders-loader class="orders-list">...</ol>

angular:

(function () {
angular.
        module('myApp')
        .directive('ordersLoader', ['$window', '$timeout', 'ordersResource', ordersloaderDirective])

function ordersloaderDirective($window, $timeout, loading, ordersResource) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.orders = ordersResource; /*ordersResource use $resource to api calls
            and then stocks the data in a array exposed in the scope*/

            $timeout(function () {
                scope.$watch(function () { return element[0].scrollTop }, function () {
                    if (*the scroll exceedes more or less 75% of the total scrollHeight*/) {
                            /*asking for more orders*/                            
                    }
                });
            }, 0);
        }

    }
}

I can't figure out where is the problem.

Solved As yeouuu suggested, there was no digest cycle after the list scroll event, so i added:

element.bind('scroll', function () {
                scope.$apply();
            });

just before the $timeout function.

Upvotes: 2

Views: 118

Answers (1)

yeouuu
yeouuu

Reputation: 1913

Whenever using plugins outside of angularJs that should trigger watcher you need to explicitly apply them. Otherwise Angular won't be aware of these changes/events.

In your case that means adding scope.$apply(); after the event.

Your edited solution:

element.bind('scroll', function () {
  scope.$apply();
});

More information can be found here about the scope life cycle: https://docs.angularjs.org/guide/scope#scope-life-cycle

Upvotes: 2

Related Questions