Black Lives Matter. Please consider donating to Black Girls Code today.
Learn about the upcoming Dash Enterprise 4.0 release in the August 5th webinar with Chris Parmer, the Inventor of Dash.

Plotly R : Modify several attributes from a single restyle button

Hello dear community :slight_smile:

I’m trying to implement a quite “simple” task:
I am trying to modify several data attributes of my graph from a single “custom button” click.

After quite many researches, trials and kind of reverse engineering, I’m still unable to achieve this behavior.

More precisely, I do successfully pass 2 arguments to the “update” method, but I am still struggling to pass a 2nd args to the restyle method.

Neither the basic documentation for the “updatemenus” usage with simples examples, nor the detailed documentation (https://plotly.com/r/reference/#layout-updatemenus) provide and explicit solution to this problem (or at least I cannot find it).

Some topics related to my question are open but are not successfully answered ([https://stackoverflow.com/questions/50841935/multiple-changes-to-data-with-buttons-in-plotly] or also [R: plotly multiple args in updatemenus with same lable] ), to which I am eager to finally find a solution :slight_smile:

I even found a solution… for the python version : [Dropdown with multiple attribute changes] , that I am unable to successfully implement from R.

Here is a Minimal Working Exemple to illustrate the problematic:

suppressMessages(library(plotly))

myData <-  data.frame ("X"=1:10, "Y1"=runif(10), "Y2"=runif(10))

fig <-  plot_ly( data=myData, type = 'scatter', mode = 'line', y = myData$Y1, x = myData$X)

fig <-  layout ( fig, title = "My MWE",
                updatemenus = list(
                                                
                    ## This one works like a charm.
                    list( type="buttons", y = 0.9,
                         buttons = list(
                             list(method = "restyle", args = list( list(mode = "line")),  label = "0 - [Restyle] 1 attribute : mode = line.") , # One way to do it.
                             list(method = "restyle", args = list("mode", "markers"),  label = "1 - [Restyle] 1 attribute : mode = markers.") # Another way of doing it.
                         )
                         ),

                    ## This one works like a charm.
                    list( type="buttons", y = 0.8,
                         buttons = list(
                             list(method = "restyle", args = list( list (y = list(myData$Y1))),  label = "0 - [Restyle] 1 attribute : y = Y1."),
                             list(method = "restyle", args = list("y", list(myData$Y2)),  label = "1 - [Restyle] 1 attribute : y = Y2.")
                         )
                         ),
                    
                    ## This one works like a charm.
                    list( type="buttons", y = 0.7,
                         buttons = list(
                             list(method = "update",
                                  args = list(list(visible = TRUE), list(title = "My MWE")),
                                  label = "0 - [Update] Modify 2 attributes: Visible & Title."),
                             list(method = "update",
                                  args = list(list(visible = FALSE), list(title = "Disapeared!")),
                                  label = "1 - [Update] Modify 2 attributes: Visible & Title.")
                         )
                         ),
                          
                     ## This one apply the first argument but not the second.
                    list( type="buttons", y = 0.3,
                         buttons = list(
                             list(method = "restyle",
                                  args = list( list( y = list(myData$Y1) ), list( mode = "line")),
                                  label = "0 - Modify 2 attributes via restyle: y=Y1; mode=line [Attempt A]"),
                             list(method = "restyle",
                                  args = list( list( y = list(myData$Y2) ), list( mode = "markers")),
                                  label = "1 - Modify 2 attributes via restyle: y=Y2; mode=markers [Attempt A]")
                         )
                         ),

                    ## This one apply the first argument but not the second.
                    list( type="buttons", y = 0.2,
                         buttons = list(
                             list(method = "restyle",
                                  args = list("y", list(myData$Y1), "mode", "line"),
                                  label = "0 - Modify 2 attributes via restyle: y=Y1; mode=line [Attempt B]."),
                             list(method = "restyle",
                                  args = list("y", list(myData$Y2), "mode", "markers"),
                                  label = "1 - Modify 2 attributes via restyle: y=Y2; mode=markers [Attempt B]")
                         )
                         ),
                          
                    ## This one does nothing... at least visible...
                    list( type="buttons", y = 0.1,
                         buttons = list(
                             list(method = "restyle",
                                  args = list( list("y","mode") , list(list(myData$Y1), "line")),
                                  label = "0 - Modify 2 attributes via restyle: y=Y1; mode=line [Attempt C]"),
                             list(method = "restyle",
                                  args = list( list("y","mode") , list(list(myData$Y2), "markers")),
                                  label = "1 - Modify 2 attributes via restyle: y=Y2; mode=markers [Attempt C]")
                         )
                         )
                )
                )

htmlwidgets::saveWidget(as_widget(fig), "mwe.html")

Any tips to help me understand the typing of the restyle method arguments or suggestions on how to get more than 1 argument to be interpreted would help :slight_smile:

So, I managed to find my solution. args is a list of list, then each arg is a list (seems obvious now :p).

                    ## This one works.                                                                                                                                                                                                     
                    list( type="buttons", y = 0.3,
                         buttons = list(
                             list(method = "restyle",
                                  args = list( list( y = list(myData$Y1), mode = list("lines"))),
                                  label = "0 - Modify 2 attributes via restyle: y=Y1; mode=line [The solution]"),
                             list(method = "restyle",
                                  args = list( list( y = list(myData$Y2), mode = list("markers"))),
                                  label = "1 - Modify 2 attributes via restyle: y=Y2; mode=markers [The solution]")
                         )
                         ),

Hoping it will save time and patience for others ! :slight_smile: