rcarcasses / vue-cytoscape

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

Running the layout in the afterCreated prop when using cy-elements. #17

Closed EHadoux closed 5 years ago

EHadoux commented 5 years ago

Hello, this is more to ask if it's the right behaviour than reporting an actual bug because the solution doesn't seem too crazy to be the right way to do it.

So basically, the cytoscape component is in the template like so:

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

No element is added in the config, everything is in the elements property of the parent component. What I wanted to do is to run a layout in the after function called by the afterCreated prop. Basically it was:

after(cy) {
  cy.layout({
    name: 'breadthfirst',
    circle: false,
    roots: '#existingnode',
    spacingFactor: 1,
    padding: 50,
    fit: true,
  }).run();
}

The nodes and edges were added (thanks to the v-for) but the layout was not applied. It turned out that the layout was actually applied but before the nodes were in the graph because wrapping the content of the after function into two nested nextTick worked. I think it's because:

What I don't understand though is that if I replace the after function with:

async after() {
  const cy = await this.$cytoscape.instance;
  cy.layout({
    name: 'breadthfirst',
    circle: false,
    roots: '#existingnode',
    spacingFactor: 1,
    padding: 50,
    fit: true,
  }).run();
}

it works. As if the Promise was resolved way later when everything is there.

So not everything is clear to me but this doesn't seem crazy so I put it there for the others so they don't waste time on it. If you have more explanations for that I'd be glad. Cheers!

rcarcasses commented 5 years ago

The whole point of providing a pointer to the promise to the cytoscape instance rather to the instance itself is to hide away all these mundane configurations as you have figured out :).

I would like to add that, yes, indeed, is not clear at all that it will work by just marking the function as async, I think it works because this is called after all the cy-element's were actually added, and I would like to thank you for your detailed explanation. Notice anyway, that in this repository there was already an example about how to work with layouts.

EHadoux commented 5 years ago

Notice anyway, that in this repository there was already an example about how to work with layouts.

Yes, I've seen it, however the behaviour is different there because you add the elements directly to the cy instance instead of through the cy-elements which alleviate the need to wait for Vue to render them first.

What I've done is to await the instance in the mounted() of the parent component and it seems to work so I'll stick with that for now. Thanks!