Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clear plotly click event

Tags:

r

plotly

I'm trying to use plotly click events in the context of a shiny app. Following the official demo I'm using this bit of code to update a date picker and jump to another tab in my app on click:

observe({
  d <- event_data("plotly_click", source = 'plot')
  if(!is.null(d) & (input$navPanel == 'overview')) {

    d %>% filter(curveNumber == 0) %>% select(x) -> selected_date

    updateDateInput(session, "date", value = lubridate::ymd(selected_date$x))
    updateTabsetPanel(session, "navPanel", selected = "details")
  }

However, when I then try to switch back from the details to the overview tab, I get immediately thrown back to the details tab. I'm assuming that this happens because the event is never cleared, i.e. d is not null when the tab gets changed and so the condition in the if-clause evaluates to TRUE.

So, how do I clear the click event programmatically? Adding d <- NULL to the end of the conditional doesn't seem to do it.

like image 708
RoyalTS Avatar asked Oct 04 '16 17:10

RoyalTS


2 Answers

I have same problem, and the workaround I've found is to store the old state in a global variable, and do the updates only when that variable changes and not on the !is.null()

selected_date <- 0 # declare outside the server function

server <- function(input, output, session) {
  observe({
    d <- event_data("plotly_click")
    new_value <- ifelse(is.null(d),"0",d$x) # 0 if no selection
    if(selected_date!=new_value) {
      selected_date <<- new_value 
      if(selected_date !=0 && input$navPanel == 'overview')
        updateDateInput(session, "date", value = lubridate::ymd(selected_date))
    }
  })
...
}

This also allows you to add a behaviour whenever the element is unselected

like image 179
HubertL Avatar answered Sep 30 '22 07:09

HubertL


I solved this by using shinyjs and manually resetting the event_data("plotly_click") with the help of the Shiny.onInputChange function, which sets values in the input vector manually:

library(shiny)
library(plotly)
library(shinyjs)

ui <- shinyUI(
  fluidPage(
    useShinyjs(),
    # code to reset plotlys event_data("plotly_click", source="A") to NULL -> executed upon action button click
    # note that "A" needs to be replaced with plotly source string if used
    extendShinyjs(text = "shinyjs.resetClick = function() { Shiny.onInputChange('.clientValue-plotly_click-A', 'null'); }"),
    actionButton("reset", "Reset plotly click value"),
    plotlyOutput("plot"),
    verbatimTextOutput("clickevent")
  )
)


server <- shinyServer(function(input, output) {

  output$plot <- renderPlotly({
    plot_ly(mtcars, x=~cyl, y=~mpg)
  })

  output$clickevent <- renderPrint({
    event_data("plotly_click")
  })

  observeEvent(input$reset, {
    js$resetClick()
  })
})

shinyApp(ui, server)
like image 21
shosaco Avatar answered Sep 30 '22 07:09

shosaco