datastorm-open / visNetwork

R package, using vis.js library for network visualization
Other
545 stars 125 forks source link

[enhancement] [question] Editing edges and adding additional parameters #377

Closed julianstanley closed 4 years ago

julianstanley commented 4 years ago

Hello! I'll put the question and feature request up here, and then add more information below.

Feature requests

(1) Can edges be encoded so that they have a pop-up dialog when you edit them, just like nodes? And then, can I make it so that users can encode custom edge information?

If that feature would be broadly applicable to other users, then I can work on implementing it.

(2) Can there be interactivity between a visNetwork graph and a plotly graph? Similar to issue 229 but that seems to have stalled a couple years ago. Is there a solution besides crosstalk?

User-specific question

Based on the information below, do you think visNetwork is the best tool for me to use? For example, it seems like plotly can technically make directed graphs, it just isn't nearly as intuitive. Is there another alternative, and/or is my potential usecase for visNetwork reasonable? Thanks!

Specific use case information

I'm working on a project this summer (with the R Project and Google Summer of Code) that involves making a Shiny app for the gfpop package.

I would like to include an editable directed graph in that app. I think visNetwork seems like a great tool for that purpose since it (1) provides the manipulate option, which makes it really easy to add/edit nodes, and (2) it's easy to implement directed edges and edges that connect a node back to itself.

There are two barriers that keep visNetwork from being perfectly-suited to my purposes.

The first is the most important, which is that I want to store a lot of information in the edges, and want users to be able to edit that information.

So, for example, a typical gfpop graph has edges that include all of this information:

image

So, each edge needs to encode: (1) type, (2) parameter, (3) penalty, (3) K, (4) a, (5) min, and (6) max, and users will want to edit that information.

tdhock commented 4 years ago

hi @bthieurmel any idea if these features are possible/easy to implement, and in the scope of what you would like to maintain in visNetwork? Thanks

bthieurmel commented 4 years ago

Hi,

Possible : yes (everything is possible....!) Easy : not really... In the scope : yes but when ?

Waiting for that, you can editing network as you want using shiny apps and `visNetworkProxy functions...

bthieurmel commented 4 years ago

You're lucky, it's on progress...

tdhock commented 4 years ago

hi thanks for the response. if these features are in scope for visNetwork, and something you could maintain, then I would suggest @julianstanley try to implement these features over the summer and if that works, submit them as a PR.

bthieurmel commented 4 years ago

You can test the dev version devtools::install_github("datastorm-open/visNetwork"). Using 3 new arguments editEdgeCols, editNodeCols, and addNodeCols in manipulation.

You can have a look to new example.

bthieurmel commented 4 years ago

TO DO : can pass html input type, to treat character / number values

julianstanley commented 4 years ago

This is brilliant, @bthieurmel -- thank you so much for getting to this so quickly!

While working with the new features, I noticed one unexpected behavior: non-standard parameters in edges cannot be saved (unlike nodes, which work perfectly). I'll put an example below, and will be browsing around to see if I can figure out why this happens!

Reprex

library(visNetwork)

# The example graph will get from A to B
nodes <- data.frame(
  id = c("A", "B"),
  label = c("A", "B"),
  nodeParam = c(1, 2)
)

edges <- data.frame(
  to = c("B"),
  from = c("A"),
  id = c("A_to_B"),
  label = c("A to B"),
  edgeParam = c(1)
)

visNetwork(nodes = nodes, edges = edges) %>%
  visEdges(
    arrows = "to", physics = FALSE, # Makes it easier to select edges
  ) %>%
  visOptions(manipulation = list(
    enabled = TRUE,
    editEdgeCols = c("id", "from", "to", "label", "edgeParam"),
    editNodeCols = c("id", "label", "nodeParam"),
    addNodeCols = c("id", "label", "nodeParam")
  ))

Problem

So, I expect to see 'nodeParam' in nodes and 'edgeParam' in the edge.

I see nodeParam, but edgeParam is undefined:

image

If I try to edit that edgeParam to make it correct, save, and re-open the edge, my correction disappears:

image

(Note: that event is still picked up by visNetworkProxy, though)

But it works just fine if I try to edit one of the original values:

image

Editing nodeParam works just fine, though.

Debugging attempts

After editing an edge, if I set a breakpoint in visNetwork.js at line 3970, my new data (edgeParam: 1) was bound to the local variable 'data' successfully. This fits with visNetworkProxy picking up the change, I think.

The error seems to pop up at line 2980 (or a few lines below if editEdge is true). When I set a breakpoint there, I noticed that data does not contain edgeParam. Consequently, the innerHTML of editedge-edgeParam gets set to undefined.

Where does the data parameter passed to that function come from? My callstack just seems to go into vis-network.min.js

bthieurmel commented 4 years ago

Hi,

It's fix for edges extra columns + passing html input type (for example update width, size, ...) :

# choose columns to edit + input html type (text, number, ...)
# https://www.w3schools.com/tags/att_input_type.asp
visNetwork(nodes, edges) %>% 
  visOptions(manipulation = list(enabled = T, 
                                 editEdgeCols = c("label"), 
                                 editNodeCols = list(
                                    "text" = c("id", "label", "title"),
                                    "number" = c("size")
                                 ), 
                                 addNodeCols = c("label", "group")))