I am working on a shiny app where on load it shows a default table. Have a user input which when I enter and click on run should update the table. And also when clicked on reset it should show the default table.As of now I am able to view the default table and nothing happens when I click on the run button.
optimzation <- function(input, output, session, data,budget,run,reset) {
v <- reactiveValues(data = data)
observeEvent(run, {
v$data <- data %>% mutate(carb = mpg * budget)
})
observeEvent(reset, {
v$data <- data # your default data
})
output$mod_table <- DT::renderDataTable({
DT::datatable(v$data, filter = "top")
})
}
optimzationUI <- function(id) {
ns <- NS(id)
dataTableOutput(ns("mod_table"))
}
shinyApp(
ui = basicPage(
mainPanel(
numericInput("budget_input", label = h5("Total Budget"), value = 9000000),
actionButton("opt_run", "Run"),
actionButton("opt_reset", "Reset"),
tags$hr(),
optimzationUI("optimize")
)
),
server = function(input, output) {
demodata<-mtcars
callModule(optimzation,"optimize", demodata,budget=input$budget_input,run=input$opt_run,reset = input$opt_reset)
}
)
Created on 2019-02-13 by the reprex package (v0.2.1.9000)
It seems you need to be more careful when passing global user input to a shiny module. It seems it will "break" the reactivity. You can fix this my explicitly passing in a reactive object. Here's the updated module. Note the added ()
to get the current reactive value.
optimzation <- function(input, output, session, data, budget,run,reset) {
v <- reactiveValues(data = data)
observeEvent(run(), {
v$data <- data %>% mutate(carb = mpg * budget())
})
observeEvent(reset(), {
v$data <- data
})
output$mod_table <- DT::renderDataTable({
DT::datatable(v$data, filter = "top")
})
}
optimzationUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("mod_table"))
}
and here's the changed app. note the explicit reactive(input$....)
library(shiny)
library(dplyr)
shinyApp(
ui = basicPage(
mainPanel(
numericInput("budget_input", label = h5("Total Budget"), value = 9000000),
actionButton("opt_run", "Run"),
actionButton("opt_reset", "Reset"),
tags$hr(),
optimzationUI("optimize")
)
),
server = function(input, output) {
demodata<-mtcars
callModule(optimzation,"optimize",
data=demodata,
budget=reactive(input$budget_input),
run=reactive(input$opt_run),
reset = reactive(input$opt_reset))
}
)
There are a few problems with your code that make it not reproducible currently: library(shiny)
and library(dplyr)
need to be added, and the dataTableOutput
needs to be prefixed with DT::dataTableOutput
.
The next problem (which is the actual question you're asking about) is that the values you're passing to the module are currently being passed as just regular values at one snapshot in time. They should be passed as reactives instead. It's a bit counter intuitive because we think of inputs as reactive, but when you pass input$reset
then you're passing the module the specific value at this point in time. Instead, you need to pass it reactive(input$reset)
, and then in the module you access it with reset()
instead of with reset
. The same is true for the other reactives that are passed into the module.
Here's the complete code solution:
library(shiny)
library(dplyr)
optimzation <- function(input, output, session, data,budget,run,reset) {
v <- reactiveValues(data = data)
observeEvent(run(), {
v$data <- data %>% mutate(carb = mpg * budget())
})
observeEvent(reset(), {
v$data <- data # your default data
})
output$mod_table <- DT::renderDataTable({
DT::datatable(v$data, filter = "top")
})
}
optimzationUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("mod_table"))
}
shinyApp(
ui = basicPage(
mainPanel(
numericInput("budget_input", label = h5("Total Budget"), value = 9000000),
actionButton("opt_run", "Run"),
actionButton("opt_reset", "Reset"),
tags$hr(),
optimzationUI("optimize")
)
),
server = function(input, output) {
demodata<-mtcars
callModule(optimzation,"optimize", demodata,
budget = reactive(input$budget_input),
run = reactive(input$opt_run),
reset = reactive(input$opt_reset))
}
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With