Background: I'm building a dashboard that interfaces with a MySQL database. The user specifies a coarse filter to pull data from the database and clicks "Submit", the data are plotted with ggvis
, then the user is able to play with fine filters to affect what subset of data are plotted. These fine filters depend on the data pulled from the database, therefore I generate them from the data using uiOutput
/renderUI
.
Problem: My challenge is that I want the UI to be updated based on the data before the plot is updated. Otherwise the fine filters from the old dataset are applied to the new data, which results in an error when plotting.
Example: The following example roughly reproduces the problem using mtcars
. To get the error, select 4 cylinders, click "Submit", then select 6 cylinders and click "Submit" again. In this case, when the 4 cylinder fine filter is applied to the 6 cylinder dataset only a single point is returned, which causes an error when trying to apply a smoother in ggvis
. Not the same error as I'm getting, but close enough.
library(shiny)
library(dplyr)
library(ggvis)
ui <- fluidPage(
headerPanel("Example"),
sidebarPanel(
h2("Course Filter:"),
selectInput("cyl_input", "Cylinders", c(4, 6)),
actionButton("submit", "Submit"),
conditionalPanel(condition = "input.submit > 0",
h2("Fine Filter: "),
uiOutput("mpg_input")
)
),
mainPanel(
ggvisOutput("mtcars_plot")
)
)
server <- function(input, output) {
mycars <- eventReactive(input$submit, {
filter(mtcars, cyl == input$cyl_input)
})
output$mpg_input <- renderUI({
mpg_range <- range(mycars()$mpg)
sliderInput("mpg_input", "MPG: ",
min = mpg_range[1], max = mpg_range[2],
value = mpg_range,
step = 0.1)
})
observe({
if (!is.null(input$mpg_input)) {
mycars() %>%
filter(mpg >= input$mpg_input[1],
mpg <= input$mpg_input[2]) %>%
ggvis(~mpg, ~wt) %>%
layer_points() %>%
layer_smooths() %>%
bind_shiny("mtcars_plot")
}
})
}
shinyApp(ui = ui, server = server)