rcarcasses / vue-cytoscape

cytoscape.js now inside vue.js
https://rcarcasses.github.io/vue-cytoscape
MIT License
94 stars 34 forks source link

How to configure the cytoscape component, when the elements are fetched. #7

Closed nilshae closed 5 years ago

nilshae commented 5 years ago

Hello, thanks for providing vue-cytoscape!

I struggle with the the initialization of the cytoscape component. I have to fetch my data from a REST-API and parse it to get my elements object. The problem is, that fetching returns a promise, and the component is already rendered when this promise is resolved. My solution (see code) is to use cy-elements and fetch the data in preConfig, but this seems wrong, and doesn't run the layout again.

Is there a better way to handle this?

<template>
  <div id="holder">
    <cytoscape :config="config" :preConfig="preConfig" :afterCreated="afterCreated">
      <cy-element v-for="def in elements" :key="`${def.data.id}`" :definition="def"/>
    </cytoscape>
  </div>
</template>

<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
import { initialLayout } from '@/../resources/graphLayouts';
import { defaultStyle } from '@/../resources/graphStyles';
import { fetchData } from '@/dataFetcher';

const RESOURCE_URL = 'http://localhost:8081/path/to/data.json';

@Component
export default class Graph extends Vue {
  public config: any = { style: defaultStyle, layout: initialLayout };
  public elements: any = [];

  public preConfig(cytoscape: any) {
    console.log('calling pre-config');
    fetchData(RESOURCE_URL).then((data: any) => {
      this.elements = data;
    });
  }

  public afterCreated(cy: any) {
    console.log('calling after-created');
    console.log(cy.elements());
  }
}
</script>

<style>
#holder {
  width: 100%;
  height: 800px;
}
</style>
rcarcasses commented 5 years ago

Hey @nilshae, you're welcome! So I think you have done all the things well, but you are missing to re-run the layout() method of cytoscape after you dynamically add the new elements. Notice that this is how cytoscape works and not related to vue-cytoscape at all. I just updated the src/LayoutExtensionsExample.vue with a code that illustrate how to use axios to load external data and later update cytoscape content with it. Another option is to do <cytoscape v-if="dataHasBeenLoaded"...>, start with dataHasBeenLoaded = false, load the data and then set the config elements with the data loaded and dataHasBeenLoaded = true.

Notice that in the example I used cy instance in afterCreated method to add the elements through cytoscape itself, you chose to add them by cy-elements (congrats! you got the idea!). vue-cytoscape has feature called DOM reflection (a term I invented myself) that basically (attempts) to synchronise bidirectionally changes in the cytoscape vue component (the one created by vue-cytoscape) and the real cytoscape content. Because of this, the end result should be the same.

Any other question, let me know!

nilshae commented 5 years ago

I got it! Thank you for the explanation and the extended example.

thearod5 commented 3 years ago

Hello, does the example referenced here, syc/LayoutExtensionsExample.vue, still exist? I am unable to find it.