rstudio / ggvis

Interactive grammar of graphics for R
Other
713 stars 171 forks source link

handle_click not working in shiny modules #457

Open BenjaminPeter opened 8 years ago

BenjaminPeter commented 8 years ago

See example below for bug:

both plots are displayed, but click events are only registered in the first plot.

library(shiny)                                                    
library(ggvis)                                                    

m <- function(input, output, session){                            
    mtcars %>% ggvis(~mpg, ~disp) %>%                             
       layer_points() %>%                                         
       handle_click(function(location,...){print(location)}) %>%  
       bind_shiny("plot-plot")                                    
}                                                                 

ui <- fluidPage(                                                  
                ggvisOutput("plot-plot"),                         
                ggvisOutput("plot-plot2")                         
                )                                                 
server <- function(input, output, session) {                      
   callModule(m, 'plot')                                          
    mtcars %>% ggvis(~mpg, ~disp) %>%                             
       layer_points() %>%                                         
       handle_click(function(location,...){print(location)}) %>%  
       bind_shiny("plot-plot2")                                   

}                                                                 
shinyApp(ui = ui, server = server)                                
raffscallion commented 8 years ago

This also seems to be the case for add_tooltip()

library(shiny)                                                    
library(ggvis)                                                    

all_values <- function(x) {
  if(is.null(x)) return(NULL)
  paste0(names(x), ": ", format(x), collapse = "<br />")
}

m <- function(input, output, session){                            
  mtcars %>% ggvis(~mpg, ~disp) %>%                             
    layer_points() %>%                                         
    add_tooltip(all_values, "hover") %>%
    bind_shiny("plot-plot")                                    
}                                                                 

ui <- fluidPage(                                                  
  ggvisOutput("plot-plot"),                         
  ggvisOutput("plot-plot2")                         
)                                                 
server <- function(input, output, session) {                      
  callModule(m, 'plot')                                          
  mtcars %>% ggvis(~mpg, ~disp) %>%                             
    layer_points() %>%                                         
    add_tooltip(all_values, 'hover') %>%
    bind_shiny("plot-plot2")                                   

}                                                                 
shinyApp(ui = ui, server = server)
cwickham commented 8 years ago

Came across the same problem trying to get input_slider() to work in a module.

Seems like bind_shiny() doesn't play nice with the session_proxy object coming from getDefaultReactiveDomain(). A hack is to specify session = getDefaultReactiveDomain()[["parent"]] in the call to bind_shiny() inside the module:

library(shiny)                                                    
library(ggvis)                                                    

m <- function(input, output, session){                            
  mtcars %>% ggvis(~mpg, ~disp) %>%                             
    layer_points() %>%                                         
    handle_click(function(location,...){print(location)}) %>%  
    bind_shiny("plot-plot", session = getDefaultReactiveDomain()[["parent"]])                   
}                                                                 

ui <- fluidPage(                                                  
  ggvisOutput("plot-plot"),                         
  ggvisOutput("plot-plot2")                         
)                                                 
server <- function(input, output, session) {                      
  callModule(m, 'plot')                                          
  mtcars %>% ggvis(~mpg, ~disp) %>%                             
    layer_points() %>%                                         
    handle_click(function(location,...){print(location)}) %>%  
    bind_shiny("plot-plot2")                                   

}                                                                 
shinyApp(ui = ui, server = server) 

But this feels a little like it's going against the principles of modules (it probably wouldn't work nicely if you start nesting modules). It seems to work ok with multiple instances of the same module, i.e.

library(shiny)                                                    
library(ggvis)                                                    

m_output <- function(id){
  ns <- NS(id)
  ggvisOutput(ns("plot"))
}

m <- function(input, output, session){  
  ns <- session$ns

  tmp <- mtcars %>% ggvis(~mpg, ~disp) %>%
    layer_points() %>%                                      
    handle_click(function(location,...){print(location)}) %>% 
    bind_shiny(ns("plot"), 
      session = getDefaultReactiveDomain()[["parent"]]) 
}                                                                 

ui <- fluidPage(                                           
  m_output("plot1"),
  m_output("plot2")
)  

server <- function(input, output, session) {                      
  callModule(m, "plot1") 
  callModule(m, "plot2") 

}                                                                 
shinyApp(ui = ui, server = server)   
laderast commented 8 years ago

Is there any other workaround to this issue? For my module that uses ggvis and add_tooltip I tried using bind_shiny with session = getDefaultReactiveDomain()[["parent"]] in my app module but it's throwing a bind_shiny() must be run inside a shiny app. error

jazon33y commented 7 years ago

I also see the "bind_shiny() must be run inside a shiny app." error. Is the only currently functioning workaround to just re-scope modules around ggvis bindings?