plotly / dash-cytoscape

Interactive network visualization in Python and Dash, powered by Cytoscape.js
https://dash.plot.ly/cytoscape
MIT License
595 stars 120 forks source link

Cytoscape doesn't re-render node styling when changes made to elements #127

Open MonkeyChap opened 3 years ago

MonkeyChap commented 3 years ago

Description

Cytoscape doesn't re-render node styling when changes made to elements. It looks like the library is only doing a very shallow comparison / diff of the elements list, so it misses changes to the "style" dictionary object.

Steps/Code to Reproduce

Create a list of nodes and edges, each with their own style entries. Modify the styles, and inject it back into the component using a callback. There will be no changes to the displayed style - background color, image, border, etc. all remain the same.

I even tried creating a completely new list (i.e. a modified copy), but it seems to be basing its diff on the identity of the nodes and edges rather than the list.

BTW - Dash is really great, but this is a bit of a show-stopper at the moment. A work-around would be awesome. As an absolute last resort, I might have to replace all their IDs on modification but this will have impact on nearly every bit of my app...so hopefully you know a better workaround than this.

Expected Results

The style changes should be detected (or some way to force detection) and for the renderer to update.

Actual Results

No changes to the styles at all. If I load new elements, then their styling is correct the first time they're loaded...then immutable after that.

Versions

latest version

markFriel commented 3 years ago

I was facing a similar issue.

For a bit of context, I was looking to highlight the shortest path between two nodes, I would run a graph algorithm that would give me the edges in the path and then I would set a property Highlighted = "True" within the edges and then pass back the updated elements as output in the callback.

In the Stylesheet, there would be a property: { 'selector': '[selected ^= "True"]', 'style': { 'line-color': 'green' } }

I found that having the stylesheet back as output in the callback allowed me to update the styling of the nodes and edges. I think it must trigger a deeper comparison of the element list than just passing back the elements list by itself. To be clear I didn't have to make any changes to the stylesheet, I just had to pass it back as output

@MonkeyChap I think this is may be a better workaround than updating the Node IDs

MonkeyChap commented 3 years ago

Hi - thanks Mark. I ended up doing something similar, but as it involves a lot of node types I have to regenerate the Stylesheet every time. It seems to work, though every now and then some nodes don't get styled. I can't figure it out or reproduce it reliably, but it'll do for now.