My objective is to determine the offset and height of list items. Once I have those values, I trigger a function in a parent directive. Ultimately, this will involve transitioning elements in and out as they come into view.
Issue: Due to the use of ng-repeat
(for reasons unknown), the values for el[0].offsetheight
and
el[0].getBoundingClientRect().top;
appear to be somewhat arbitrary unless I place a $timeout
around the logic. I suspect this is because the styles need time to render?
Query: How can I obtain accurate offset and height values without resorting to using a $timeout
or implementing a $watch
.
HTML:
<dt spyed ng-repeat="exp in experiences">
...
</dt>
JS:
app.directive('spyed', function () {
return {
require: '^scrollSpyer',
link: function(scope, el, attrs, ctrl) {
// The offset value seems random after the first ng-repeat item
var offset = el[0].getBoundingClientRect().top;
// Similarly, the height value appears random after the first ng-repeat item
var theHeight = el[0].offsetHeight;
// This triggers the expMapper on the parent directive.
ctrl.expMapper(offset, theHeight);
}
};
});
Note regarding why I am avoiding using a watcher:
The reason I prefer not to utilize a watcher is because I am pushing these values to a collection in the parent directive. I wish to avoid constantly resetting the array, which would happen if ctrl.expMapper()
kept firing due to two-way binding.
Parent Directive:
app.directive('scrollSpyer', function ($window, Experiences) {
return {
controller: function($scope){
$scope.experiences = [];
this.expMapper = function(offset, height) {
$scope.experiences.push({'offset': offset, 'height': height, 'inView': false});
};
},
link: function(scope) {
var i = 0;
angular.element($window).bind('scroll', function() {
if(i < scope.experiences.length) {
if (this.pageYOffset >= scope.experiences[i].offset) {
Experiences.status.push(scope.experiences[i]);
i++;
} else {
console.log('middle');
}
}
scope.$apply();
});
}
};
});