Skip to content

Model approach used in checkbox tree is incompatible with Vue 3

While working on &7203 I've discovered that our models approach taken in checkbox tree is not compatible with Vue 3

What we basically do? We create a tree model inside Vue component. At this point Vue 2 patches this instance (and all underlying node instances) to be reactive, by defining getters/setters on instance

This means that when we invoke any method on models( for example toggleAllOptions Vue 2 is capable to track changes and update our model accordingly

This is not the case for Vue 3. Vue 3 wraps our model in proxy, instead of patching it.

So, any changes which are made inside the model are not tracked by Vue 3 reactivity system (because inside class instances this is pointing to instance, not to the proxy where Vue track changes). Basically this results in this test failiing

What approaches we potentially could take: (this list is not completed, I'm open to new suggestions!):

  • split functions and state (remove classes). So basically instead of calling tree.toggleAllOptions we will write something like toggleAllOptions(tree). Since we will be getting rid of this our functions will receive proper Vue proxies for Vue 3 and this approach is compatible with Vue 2

  • Put all state in a dedicated field inside classes, which will be explicitly made reactive using Vue.observable (something like this.state = Vue.observable({ /* ... */ })). Since our data will remain explicitly reactive this will be compatible with both Vue2 and Vue3 (in Vue3 we will simply replace Vue.observable with Vue.reactive

  • implement models as renderless Vue instance (so created via new Vue). I'm not a big fan of this approach, but I've seen it on some projects

Important note: we have a number of similar class-based storages in main gitlab-org/gitlab codebase. It would be great to figure out approach, which we will consider universal for such migration (and add it to our frontend documentation)