antoniandre / vue-cal

A Vue.js full calendar, no dependency, no BS. :metal:
https://antoniandre.github.io/vue-cal/
MIT License
1.23k stars 234 forks source link

onViewChange(ScrollTo) only works with 300ms delay #492

Closed LouisRoyT closed 2 years ago

LouisRoyT commented 2 years ago

Hi! First off, thanks for the great work with your library.

We have users in different timezones, and we want to be able to show events in the whole 24h period, but still have a good UX. Ideally, users could always see all events, but the view is always initially scrolled into a scrollPosition that makes sense (both on 1st load and when switching to/from day/week views)

I added watchers on vuecal's view.id property, to trigger scrollToOfficeHours() when it changes. However, it only seems to work if I wait a bit before calling scrollToOfficeHours(). It's as though if I call scrollToOfficeHours() too early, the component is not rendered yet... or something like that...

Here's a codepen that reproduces my problem: https://codepen.io/louisroyt/pen/abYawgE Comment/Uncomment lines 20 and 21 to see the working/not-working version.

P.S. Initially, we had a "showFullDay / showOnlyOfficeHours" button, which toggled :time-to=[17*60, 24*60] and :time-from=[0, 8*60] That worked pretty well, but we would prefer this solution :D

antoniandre commented 2 years ago

Hi @LouisRoyT,

Thanks for your feedback and repro. This is actually a normal behavior. Indeed when Vue Cal is ready, or when the view changes (from variable change in Vue Cal codebase) the DOM needs to be updated and Vue does this internally since it's data driven. A DOM repaint usually takes 250 to 300 ms but it depends on the content.

Vue Cal emits the ready event as soon as it is ready in the data so you can act from outside as soon as possible, like change the data, do an API fetch or whatever. But in case you need to do a DOM related task like scrolling, you need to wait for the DOM to also be ready, and the animation to be done. Usually 300ms is a safe bet - and I don't think it is noticeable A slightly nicer approach is to use $nextTick, a Vue hook that is triggered when Vue internally finished updating the DOM after a data change. This way, you are sure you wait the smallest amount of time possible. This will work for the @ready event, since there is no Vue Cal animation, but when the view changes, there is a default animation of 250ms.

image

That means in this case, you need to wait more than 250ms to have a stable view where you can auto-scroll. Putting 260ms would work, but if we can notice the jump of hours, then I would make this explicit by scrolling smoothly so it does not look like a bug. But maybe you don't need the hours before that at all if you always scroll to business hours, and you can set the time-from instead of scrolling - like you had before. It could be an easier UX.

I've updated your Codepen: https://codepen.io/antoniandre/pen/GRxzBPm?editors=1010

On a side note, this.$watch("$refs.vuecal.view.id") on mounted, can be replaced with @view-change="scrollToOfficeHours" directly from the template since Vue Cal emits a view-change event.

hope it helps.

antoniandre commented 2 years ago

By the way, if you prefer, you can also disable the transition on view change: transitions="false".

LouisRoyT commented 2 years ago

Hi @antoniandre. Thanks so much for the replies. The combination of $nextTick and setting transitions=false works perfectly for me.

P.S. I also refactored to use @view-change. Looks cleaner. Ty.