Patrick
Patrick

Reputation: 3498

Angularjs directives updating to changes in DOM attribute values

I've been working on a scrollspy module for Angularjs. I've run into the problem where if the page is dealing with dynamic content, the scrollspy data (element positions) quickly becomes outdated. What is the angularjs way of dealing with issues such as this?

Should any directive that performs DOM manipulation $broadcast an event that the scrollspy module looks out for - allowing it to refactor its position data?

Should the scrollspy module check every x seconds for a change in scrollHeight with $timeout?

Or even better, is there a way to bind and watch for DOM attribute value changes (attributes such as offsetTop, offsetHeight, scrollHeight, not data attributes)?

Update: Added code base to GitHub

Upvotes: 6

Views: 3407

Answers (3)

plong0
plong0

Reputation: 2188

Something like this should work... doesn't seem to update with CSS transitions though.

scope.$watch(function(){
    return elem[0].offsetLeft;
}, function(x){
    console.log('ITEM AT '+x);
});

Upvotes: 1

Patrick
Patrick

Reputation: 3498

Mutation Observers seem to be the facility needed, unfortunately they are only supported by the latest browsers.

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
if( MutationObserver ) {

    for ( var i = 0; i < spyService.spies.length; i++ ) {
        var spy = spyService.spies[i].scope.spy;
        var target = document.getElementById(spy);

        var config = {
            attributes: true,
            childList: true,
            characterData: true,
            subtree: true
        };
        var observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                console.warn('mutation observation');
            });
        }).observe(target, config);
    }
}
else {
    console.warn('no mutation observers here');
    $interval(function() {
        angular.element( document ).ready( function() {
            console.log('refreshing');
        });
    }, 2000);

}

Currently searching for a polyfill that actually works.

EDIT: Added polling as a fallback if Mutation Observers aren't supported.

Upvotes: 6

Chris Nicola
Chris Nicola

Reputation: 14574

Without the code I'm stabbing in the dark a bit, but I would suggest your scrollspy module check every time $rootScope receives a $digest call. So use $rootScope.$watch.

$rootScope.$watch(function() {
  // Update scrollspy data here
}

Upvotes: 0

Related Questions