Reputation: 237
I have an directive which sets two classes to an element to identify which quadrant it is in the browser window (top left, top right, bottom left, bottom right). Code is similar to this:
angular.module('positionerDirective', [])
.directive('positioner', function() {
return {
restrict: 'A',
link: function(scope, element){
var top = element[0].offsetTop;
var left = element[0].offsetLeft;
//do whatever math you need here
angular.element(element).addClass(class you need);
}
};
});
The problem I have is that if the user scrolls, or changes the screen size, the quadrant could change, and I need the classes to update if this happens. So my question is, how can I make the directive run again if the left / top changes?
Upvotes: 1
Views: 77
Reputation: 8789
You can add controller to your directive, subscribe in it to DOM events of resize
and scroll
and update class accordingly. Here is an example of doing it:
JavaScript
angular.module('positionerDirective', []).
directive('positioner', function() {
return {
restrict: 'A',
scope: true, // <- create isolated scope
link: function(scope, element) {
var el = element[0];
scope.$watch(function() {
return (el.offsetTop - scope.scrollTop)+':'+(el.offsetLeft - scope.scrollLeft); // <- check element class is to be updated
}, function() {
el.className = 'top-'+(el.offsetTop - scope.scrollTop)+' left-'+(el.offsetLeft - scope.scrollLeft); // <- apply new element class
});
},
controller: ['$scope', '$window', function($scope, $window) {
$scope.updatePosition = function() {
$scope.scrollTop = $window.document.body.scrollTop,
$scope.scrollLeft = $window.document.body.scrollLeft;
if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') { // <- Avoid call of $apply while digest is already running
$scope.$apply();
}
}
angular.element($window).on('resize scroll', function() { // <- subscribe to DOM events and update scope accordingly
$scope.updatePosition();
});
$scope.updatePosition(); // <- set initial values of $scope.scrollTop and $scope.scrollLeft
}]
};
});
Plunker: http://plnkr.co/edit/wvYTZ18gY2N5ABODyZO7?p=preview
Upvotes: 1