angularjs-scroll-glue
angularjs-scroll-glue copied to clipboard
scroll goes too soon
Hello here. I'm trying to use this directive for my case, and it seems it doesn't work properly.
I have scrollable div, with AJAX messages there. So, I expect, that after message is added, container will scroll down for it. But, it doesn't work.
My inverstigations:
$window.addEventListener('resize', scrollIfGlued, false);
doesn't call the callback. Callback is called from scope.$watch(scrollIfGlued);
immediately after AJAX query done (it's noticeable from stacktrace), and scroll
function is called too early, when el.scrollHeight
isn't enought high.
The solution is
scope.$watch(function() {
$timeout(scrollIfGlued, 0, false);
});
I'd commit pull request, but test fails for me, and I can't repair them.
I understand, it sounds like edge case, but it will make directive more robust
I can confirm that the "fix" from kukunin is working for me, I have a similar case where messages are updated asynchronically .
:+1: Looking forward for a fix to async messages as well
My bad it does seem to be fixed in the latest version, npm is still on 2.0.4 that's why it wasn't working on my end.
Yea I have requested NPM parity in a separate issue, but have not heard from the author. It has been 4.5 months since I created that issue. I think this author is not-so-committed to this being a public project. Maybe someone will eventually fork and be committed to maintaining?
Just want to note that:
scope.$watch(function() { $timeout(scrollIfGlued, 0, false); });
Did not work for me, but:
scope.$watch(function() { $timeout(scrollIfGlued, 100, false); });
Did.
I can confirm this. The scrollIfGlued
function is called for every $digest cycle. This can cause problems like threema-ch/threema-web#18 ("scrolling up sometimes fails") if a lot of events are dispatched (e.g. when there's an animation running at the same time in the same scope), because the function is called before the scrolling event has finished and is out of the "glue" zone.
In addition to running the function at the end of the $digest cycle, I also wanted to delay it a bit (like @twelve6 mentioned) and add some debouncing. I ended up at this:
scope.$watch(() => {
const ctx = this;
if (ctx.watchPromise === undefined) {
ctx.watchPromise = $timeout(() => {
scrollIfGlued();
ctx.watchPromise = undefined;
}, 10, false);
}
});
This way, the scrollIfGlued
function is not called more often than once every 10ms.
It seems reasonable to debounce this behavior. If you could provide the change as a pull request, that'd be great.
Actually it still does not work properly in all cases :slightly_frowning_face: Still debugging...