vue2vis icon indicating copy to clipboard operation
vue2vis copied to clipboard

[Timeline] Limitations of using Vue component as items or groups

Open Glandos opened this issue 5 years ago • 2 comments

I'm just starting to use your (awesome :wave: ) project. I'd like to show some complex items (with images) in timeline, and since I already have some Vue components to handle this, I used your example to try it.

However, I noticed some limitations:

  • Reactivity is non-existent. Moreover, the template function is called on every select and unselect event, and it build a new component every time. I kind of solved it by caching instances of component items, but it doesn't solve the fact that changes in component state are not reflected
  • Only HTML and CSS from the initial state. The rest is ignored, and it includes events. For example, I used some router links, and they are not handled by JS event, but trigger a page reload, which is… undesired :wink:

I don't know if those limitations can be lifted. The template method from visjs-timeline seems out of control. Maybe there is something to do to hook on Vue component and call redraw when needed?

And for JS and events, I don't even think this is possible, so maybe it could be good to write it somewhere in the documentation.

Glandos avatar Dec 16 '20 09:12 Glandos

I'm glad you like it @Glandos. I too use some complex vue components in the items and I also use a JS Map to cache the components to avoid to recreate them. For the lack of reactivity within the component, I either use this.$parent either vuex. It is a bit clunky but I haven't found a better solution yet. I'm not sure I fully understand/encountered your second point, if you ever have the time to show me an example.

alexcode avatar Feb 26 '21 10:02 alexcode

Right, you remind me that I found another solution, that works really better for me. Here is a quick excerpt. First the template:

    <Timeline
      ref="timeline"
      :items="timelineItems"
      :options="timelineOptions"
    />
    <div v-show="false">
      <TimelineCard
        v-for="(item, index) in items"
        ref="itemCards"
        :key="index"
      />
    </div>

Timeline is your component, and TimelineCard is a custom component I made.

Then, the data:

  timelineItems = [] // Put your stuff here
  timelineOptions = {
    template: (item) => {
      // If using typescript, see https://github.com/visjs/vis-timeline/pull/836
      return this.$refs.itemCards[item.id].$el
    }
  }

And… this is basically it. As you can see, the trick is using refs embedded in an v-show="false" div. And now, your element belong to the Vue tree, are debuggable, reactive, hot-reloaded, etc.

Glandos avatar Feb 26 '21 11:02 Glandos