quasarframework / quasar-ui-qcalendar

QCalendar - Quasar App Extension, Vue CLI plug-in and UMD distributions available
https://quasarframework.github.io/quasar-ui-qcalendar
MIT License
424 stars 117 forks source link

Force re-render of a specific resource / row #206

Closed psarin closed 3 years ago

psarin commented 3 years ago

Is your feature request related to a problem? Please describe. I believe the request would be new functionality as I don't see anything in docs referring to this issue. I would like a way to refresh / re-render one single row / resource / interval row in the calendar.

As background, I am using day-resource view with left (resource) side showing a Room, and the right (interval) side showing time based events (absolutely positioned). The right side also has a second row (i.e., positioned below row 1 containing the time based events) for each resource that shows one single "note" associated with the resource.

Describe the solution you'd like I would like the second row (containing the note) to show / hide based on a checkbox click on the left (resource) side. Currently, I can use the events to toggle a model for show/hide, but unfortunately, the interval side for that row does not re-render / refresh based on the value of the model. It appears it only checks the model at the first render.

Describe alternatives you've considered I have considered forcing a render of the complete schedule but this is distracting to the user and takes time for complete refresh since I have about 100 rows and about 150 events in the calendar.

hawkeye64 commented 3 years ago

@psarin Any chance you can make a codepen? https://codepen.io/Hawkeye64/pen/RwwwKQL

psarin commented 3 years ago

Yes, will try to get you a code sample - will have to refactor / simply my logic before I can create an example.

FYI, I was able to do a workaround by using an Observable when the resources are created but I'm not sure if this will be the best / most performant way to do this.

hawkeye64 commented 3 years ago

@psarin My problem is I am not sure if I am visualizing the same thing you are and I'd rather be on the same "page" before trying to resolve something that may or may not be correct. I do truly appreciate it if you can get a codepen together and then we can talk more. Are you on Discord? Same name? When you have the codepen, we can try a Discord chat while looking at the pen at same time.

psarin commented 3 years ago

Hi, so I was able to create a sample at: https://codepen.io/psarin/pen/GRjoXXK?editors=1010 (unfortunately, wasn't able to save under yours).

So this version works, in the sense that you can click the checkbox on the left and it will show/hide the note on the right side. I made it work using an Observable in VueJS2 (see the showNote property) or ref() in VueJS3.

The question is: is this the correct way to do it?

Other questions:

  1. The event times might change (i.e., starttime changes from 13:00 to 14:00 for one event and from 15:30 to 15:35 for another event). Will a change of times for one event cause a re-render for all (>100) objects (i.e., the EVENT_LIST will have to be re-computed)? If so, it goes back to the original question of, possible to re-render just one row.

  2. Is there an easy way to change the height for the row, to match the height of the event plus the note (i.e., right now the note overlaps the event). I compensated by manually saving a calculated height of via Observable (not shown in the CodePen).

hawkeye64 commented 3 years ago

@psarin Thanks for doing that (btw, looks really nice!) I will look at this sometime today to see if I can fully understand the issue. It's morning here and just got up.

hawkeye64 commented 3 years ago

@psarin I finally have been able to take some time and look into this. So, what's happening is your data is not reactive. You have done that with the checkbox, so when it is toggled, Vue gets notified to redraw. There are somethings that you can do:

  1. Store your data in a Vuex store
  2. Store your data in the data() method as an array. When adding/removing items from the array, use the splice command so it doesn't break Vue's reactivity.
  3. Force reactivity on a single item as you have done (Vue.observabe)
  4. Force reactivity on the whole object (Vue.observabe)

Not much I can do from a QCalendar stand-point. This is how Vue's reactivity works. I have attached a project (that I made from your Codepen). You might want to see how I did things slightly different. calendar-test2.zip