vue-cytoscape
vue-cytoscape copied to clipboard
How to use reactivity element and insert data from vuex
Hello,
I'm trying to find out how to insert my data from my vuex store in Cyelement.
Here is an example :
<template>
<div class="possession">
<Navigation></Navigation>
<b-container fluid>
<b-row>
<b-col xl="2" lg="3" md="4">
<DNavigation></DNavigation>
</b-col>
<b-col xl="10" lg="9" md="8">
<div>
<b-tabs content-class="mt-3">
<b-tab title="Global" active>
<b-row>
<b-col xl="12" lg="12" md="12">
<div class="card card-left card-progress">
<h5>Passnetwork global</h5>
<div id="holder">
<cytoscape
:config="config"
v-on:mousedown="addNode"
v-on:cxttapstart="updateNode"
>
<cy-element
v-for="def in elements"
:key="`${def.data.id}`"
:definition="def"
/>
</cytoscape>
</div>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="Selected match" v-if="match">
<MatchInfo></MatchInfo>
<b-row>
<b-col xl="12" lg="12" md="12">
<div class="card card-left card-progress">
<h5>Passnetwork of selected team</h5>
</div>
</b-col>
</b-row>
</b-tab>
</b-tabs>
</div>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import Navigation from '@/components/Navigation'
import DNavigation from '@/components/Dashboard-Navigation'
import MatchInfo from '@/components/MatchInfo'
// import Cytoscape from '@/components/Cytoscape'
import config from '@/utils/cytoscape-config'
// import CyElement from '@/components/CyElement'
const elements = [...config.elements]
delete config.elements
export default {
name: 'possession',
components: {
'Navigation': Navigation,
'DNavigation': DNavigation,
'MatchInfo': MatchInfo
// Cytoscape,
// CyElement
},
methods: {
preConfig(cytoscape) {
console.log("calling pre-config");
},
afterCreated(cy) {
console.log("after created");
this.setCyElements(cy);
},
setCyElements(cy) {
console.log("setCyElements");
let cytoElems = [];
cy.startBatch();
cy.elements().remove();
for (let el of cytoElems) {
cy.add(el);
}
cy.endBatch();
cy.fit();
}
},
data() {
return {
config,
elements: [
{
data: { id: "1" , name: "Arias", weight: 25, totpass: 8, faveColor: "#14387F", faveShape: "ellipse", playername: "Arias"},
position: { x: 10, y: 10 }
}
]
}
},
computed: {
match() {
return this.$store.getters.match
}
}
}
</script>
<style>
#holder {
width: 1200px;
height: 800px;
}
</style>
This code works when loading the view for the first time. If I navigate in an other view and return to the same view later, he does not charge me the elements anymore.
I probably missed a step.
Thanks for your help.
Hi @jrpersico, first thing I notice is that you are adding elements to cytoscape
both with cy-elements
and manually in the preConfig
hook, this would lead to unpredicted behaviour. I would suggest you to use only the cy-elements
. Now to get the cy-elements
updated you may need to change the key
as to trigger the vue
rendering of the component, or you can make sure yourself that the entire <cytoscape ...
component gets re-rendered when you enter to your view, it may be the case that vue-router
is caching your view somehow.
There is little help I can offer without seeing the code in context.
Hi @rcarcasses, thank you for your return. I corrected the code to load the element only once in cyelement.
Here is the code:
<template>
<div class="possession">
<Navigation></Navigation>
<b-container fluid>
<b-row>
<b-col xl="2" lg="3" md="4">
<DNavigation></DNavigation>
</b-col>
<b-col xl="10" lg="9" md="8">
<div>
<b-tabs content-class="mt-3">
<b-tab title="Global" active>
<b-row>
<b-col xl="12" lg="12" md="12">
<div class="card card-left card-progress">
<h5>Passnetwork global</h5>
<div id="holder">
<cytoscape :config="config">
<cy-element v-for="element in elements" :key="element.id" :definition="element" />
</cytoscape>
</div>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="Selected match" v-if="match">
<MatchInfo></MatchInfo>
<b-row>
<b-col xl="12" lg="12" md="12">
<div class="card card-left card-progress">
<h5>Passnetwork of selected team</h5>
</div>
</b-col>
</b-row>
</b-tab>
</b-tabs>
</div>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import Navigation from '@/components/Navigation'
import DNavigation from '@/components/Dashboard-Navigation'
import MatchInfo from '@/components/MatchInfo'
// import Cytoscape from '@/components/Cytoscape'
import config from '@/utils/cytoscape-config'
// import CyElement from '@/components/CyElement'
const elements = [...config.elements]
delete config.elements
export default {
name: 'possession',
components: {
'Navigation': Navigation,
'DNavigation': DNavigation,
'MatchInfo': MatchInfo
// Cytoscape,
// CyElement
},
methods: {
},
data() {
return {
config,
elements: [
{
data: { id: "1" , name: "Arias", weight: 25, totpass: 8, faveColor: "#14387F", faveShape: "ellipse", playername: "Arias"},
position: { x: 100, y: 100 }
}
]
}
},
computed: {
match() {
return this.$store.getters.match
}
}
}
</script>
<style>
#holder {
width: 1200px;
height: 800px;
}
</style>
However I still have the same problem, the Vue only starts the first time.
How can I restart the cytoscape element everytime I call the vue?
Thank you for your help.
Hi @rcarcasses, do you have any idea ?
Thank you for your help.
Hi @jrpersico, sorry but I can't see an issue with vue-cytoscape
itself here. The only help I can provide you I guess is to comment you that I personally have use vue-cytoscape
with vuex
and things get re-rendered as expected. I would recommend you to read the elements
from vuex
state through a getter
or similar, right now it seems to me that you have hardcoded it.
I'm having a similar problem
I see in all your examples you use the component import Cytoscape from './components/Cytoscape'
without a plugin. When I try using Vue.use(VueCytoscape)
(Which I see you're using in your parent app), then use the plugin as outlined in the README, I can only render on first load when dealing with extensions. ~The error I get is Error: Can not register
edgehandlesfor
coresince
edgehandles already exists in the prototype and can not be overridden
~
This issue actually happens in any hot reload/SPA page change
A simplified (broken) component is below
<template>
<div id="holder">
<!-- @mousedown="addNode" -->
<cytoscape
:config="config"
:pre-config="preConfig"
:after-created="afterCreated"
@cxttapstart="updateNode"
>
<cy-element
v-for="def in elements"
:key="`${def.data.id}`"
:definition="def"
/>
</cytoscape>
</div>
</template>
<script>
import Vue from 'vue'
import VueCytoscape from 'vue-cytoscape'
import 'vue-cytoscape/dist/vue-cytoscape.css'
import edgehandles from 'cytoscape-edgehandles'
import DataMap from './utils/DataMap'
// NOTICE, I USE 'use' HERE
Vue.use(VueCytoscape)
export default {
name: 'App',
props: {
config: {
required: true,
type: Object,
},
defaultElements: {
required: true,
type: Array,
},
elementData: {
default: () => [],
type: Object,
},
},
data() {
const dataMap = new DataMap(this.elementData.steps)
const elements = dataMap.getData()
return {
i: 0,
elements,
}
},
methods: {
preConfig(cytoscape) {
cytoscape.use(edgehandles)
cytoscape.use(nodeLabel)
},
async afterCreated(cy) {
cy.edgehandles().enable()
},
},
}
</script>
I've also tried employing this method outlined here: https://github.com/cytoscape/cytoscape.js/issues/1585, but it doesn't seem that it is properly registered in the preConfig hook in time...
@jrpersico, did you gain any traction on this
Hello @joshhoegen, I still can not solve my problem unfortunately ... Keep me informed if you can move forward
@jrpersico, I just ended up using the bare cytoscapeJs lib. It wasn't that hard to implement and found it much easier to do some basic things
I started using this library because I wanted reactive data binding to my cytoscape instance, since cytoscape isn't itself reactive. You either have to remove and re-add the elements that changed, or call setter functions like ele.data(newData).
I dug into the code, and this library treats cytoscape as if it is reactive, sending observers into the instance so the data updates. This doesn't work because, in most cases, cytoscape isn't listening for a change in the data. At this point, you basically have to re-mount all of your CyElements when the data changes for cytoscape to re-draw them.
I'll submit a PR shortly for an update that adds genuine reactivity to the library, so that changes in the parent component's "elements" array propagate in the cytoscape instance.