Search code examples
rshinyhoverggvis

ggvis hover ability in for loop in shiny app


I am trying to create a variable number of plots in a shiny app, each with hover ability from ggvis using add_tooltip() to display actual data points. To create a variable number of plots I am using a for loop. See below for a toy example that can be run on its own.

For some reason in my code the hover over ability only works correctly for the final plot that is created. Does anyone know how I might be able to fix this or maybe have a suggestion for a better approach?

Thanks!

library(shiny)
library(ggvis)

# Define ui for variable amounts of plots
ui <- fluidPage(
  fluidRow(

  uiOutput("mydisplay")
)
)

server <- function(input, output) {

# toy data example
  x = data.frame(
    id = 1:30,
    myname = c(rep("First 10",10),rep("Second 10",10),rep("Third 10",10)),
    stringsAsFactors = F
    )

# ggvis add_tooltip() function
  all_values <- function(x) {
    if(is.null(x)) return(NULL)
    row <- mydf[mydf$id == x$id, c("id","myname") ]
    paste0(names(row), ": ", format(row), collapse = "<br />")
  }

# For loop to create variable number of plots
  for (k in 1:length(unique(x$myname))){

    mydf = subset(x,x$myname==unique(x$myname)[k])
    mydf %>% ggvis(~id, ~id) %>% 
      layer_points(size := 30, key := ~id) %>% 
      add_tooltip(all_values,"hover") %>% 
      bind_shiny(paste0("p_",k), paste0("p_ui_",k)) 

  }

# For displaying in the UI
  output$mydisplay = renderUI({

lapply(1:length(unique(x$myname)), function(j) {
  fluidRow(
    column(7, ggvisOutput(paste0("p_",j)))
  )
    })
    })
    }

# Run the application 
shinyApp(ui = ui, server = server)

Solution

  • Answered my own question thanks to this question here. The ggvis code needs to be wrapped in a reactive({}) function. Hope this helps someone.