Within the link function part of a directive we have access to the element
object. I wish to determine if the element
object is within the current viewport / if it is available.
I currently have the following:
link: function (scope, element, attrs, controller) {
var page = angular.element(window);
page.bind('scroll', function () {
var windowScroll = page[0].pageYOffset,
windowHeight = page[0].innerHeight;
// elementScroll = element.xpos; - this is undefined?
// elementScroll = element.getBoundingClientRect().top - this does not work... undefined?
// elementScroll = element[0].getBoundingClientRect().top - this does not work... undefined?
// ... logic follows that if elementScroll is between windowScroll & windowScroll + windowHeight it is visible!
});
I just can't seem to get the x and y positions for my specific element (the directive may be repeated many times).
Please note that I do not intend to install or use jQuery in my application.
ng-init directive It is used to declare and assign values to the variables for an AngularJS application.
ng-app: The ng-app Directive in AngularJS is used to define the root element of an AngularJS application. This directive automatically initializes the AngularJS application on page load. It can be used to load various modules in AngularJS Application.
Scope in a Directive Well, all of the directives have a scope associated with them. This scope object is used for accessing the variables and functions defined in the AngularJS controllers, and the controller and link functions of the directive.
The ngRef attribute tells AngularJS to assign the controller of a component (or a directive) to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM element to the scope. The ngRepeat directive instantiates a template once per item from a collection.
You can use element[0].getBoundingClientRect
, it works - there is an example:
http://plnkr.co/edit/2eOw3B0MaM2vw3bQuFnf
If you need to track element visibility in angular directive, except scroll
you also need to handle events: DOMContentLoaded
, load
and resize
. Also it would be better to create only one handler for those events, and stop tracking element when directive is destroyed
app.directive('trackVisibility', function(){
function isVisible(el) {
var rect = el.getBoundingClientRect();
var clw = (window.innerWidth || document.documentElement.clientWidth);
var clh = (window.innerHeight || document.documentElement.clientHeight) ;
// checks if element is fully visible
//return (rect.top >= 0 && rect.bottom <= clh) && (rect.left >= 0 && rect.right <= clw);
// checks if part of element is visible
return (rect.left <= clw && 0 <= rect.right && rect.top <= clh && 0 <= rect.bottom);
}
var reg = [];
function register(element, fn) {
reg.push([element, fn]);
}
function deregister(element) {
reg = angular.filter(reg, function (item) {
return item[0] !== element;
});
}
angular.element(window).on('DOMContentLoaded load resize scroll', function () {
angular.forEach(reg, function (item) {
item[1](isVisible(item[0]));
});
});
return {
restrict: 'A',
link: function (scope, element, attrs, controller) {
register(element[0], function(isVisible){
scope.$apply(function(){
scope.isVisible = isVisible;
})
});
scope.$on('$destroy', function(){
deregister(element);
})
}
};
});
there is an example: http://plnkr.co/edit/VkCgBvGnCWZ0JCM8tlaJ
I have used this approach to dynamically load images when they become visible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With