I tried to lazy load images using Intersection Observable in my angular 7 application. I called Intersection Observable from ngAfterViewInit lifecycle hook. But when i load the application, callback is called twice, once with all the isIntersecting values as true and the next one with the correct isIntersecting values. I am confused with this behaviour.
ngAfterViewInit() {
const imgOne = document.querySelectorAll('[data-class]');
const options = {
// root: document
// threshold: 0
};
const observer = new IntersectionObserver((entries, observer) => {
console.log(entries.length);
entries.forEach((entry) => {
// console.log(entry);
if (!entry.isIntersecting) {
return;
} else {
const el = entry.target;
if (el.id === ('test' + this.testCount)) {
console.log(entry);
}
// observer.unobserve(entry.target);
}
});
});
imgOne.forEach((eachQuery) => {
observer.observe(eachQuery);
});
}
I tried to lazy load images using Intersection Observable in my angular 7 application. I called Intersection Observable from ngAfterViewInit lifecycle hook. But when i load the application, callback is called twice, once with all the isIntersecting values as true and the next one with the correct isIntersecting values. I am confused with this behaviour.
ngAfterViewInit() {
const imgOne = document.querySelectorAll('[data-class]');
const options = {
// root: document
// threshold: 0
};
const observer = new IntersectionObserver((entries, observer) => {
console.log(entries.length);
entries.forEach((entry) => {
// console.log(entry);
if (!entry.isIntersecting) {
return;
} else {
const el = entry.target;
if (el.id === ('test' + this.testCount)) {
console.log(entry);
}
// observer.unobserve(entry.target);
}
});
});
imgOne.forEach((eachQuery) => {
observer.observe(eachQuery);
});
}
https://stackblitz./edit/angular-wqbuyr
UPDATE : Now intersection observer is called perfectly, but now a issue occured. Since we are using document.querySelectorAll which returns a static node list, once the array is updted node list is not updated. If i try to use document.getElementsByClassName, an error throws as it is not an Node list ???
Share Improve this question edited Sep 13, 2019 at 5:20 Ram asked Sep 10, 2019 at 15:29 RamRam 61111 silver badges21 bronze badges 8-
Have you tried by this way
observer.observe(imgOne);
, no need foreach. – Shohel Commented Sep 10, 2019 at 16:59 -
Use the class into queryselector not the data attribute
observer.observe(document.querySelectorAll('img.lzy_img'));
– Shohel Commented Sep 10, 2019 at 17:02 - It will thrown an error - 'Argument of type 'NodeListOf<Element>' is not assignable to parameter of type 'Element'.' as observe gets a single element as its argument not an array of elements. – Ram Commented Sep 10, 2019 at 18:48
- Please create the example to stackblitz – Shohel Commented Sep 11, 2019 at 8:45
- stackblitz./edit/angular-wqbuyr – Ram Commented Sep 12, 2019 at 7:35
2 Answers
Reset to default 5Maybe this also works:
if (entry.isIntersecting && Math.floor(entry.intersectionRatio) === 1) {
const el = entry.target;
if (el.id === ('test' + this.testCount)) {
console.log(entry);
}
} else {
return;
}
"If you dont' check intersectionRatio ratio === 1, the observed element will trigger the callback twice, because when immediately passing/leaving 100% threshold, observer will trigger isIntersecting = true, intersectionRatio ~= 0.9 (maybe bug). Chrome somehow gets intersectionRatio slightly above 1 on the first box, so floor the value"
Source: https://codepen.io/mmanney/details/erpZbd
I solved the issue by removing ngOnInit(), as it was triggering ngAfterViewInit() again after loading.