I have a general question about when users make a change to an input value in Shiny and how to respond to that change efficiently.
First, I will paint the picture with words, then I will try and create a minimal version of what I am talking about with code.
Action: User changes drop down menu to select a specific item.
Reaction: A filter function, based on that user input is applied to an output variable and displayed on the screen.
Issue: I want to apply that filter for all of my output values on display (without having to call that filter function again).
Currently, I am calling the same function with my filters as arguments to that function for each of my outputvariables. This seems like a waste of computation because I really only need to call the function one time, use ALL of that data to populate all of my output values.
I feel like I am missing something fundamental here.
Ideally, I would like to be able to call something like this (returns a list containing a tibble and some other calculated values):
test <- reactive({se_report_filtered(my_filter = input$PM_ID,
start_year = input$obs[1],
end_year = input$obs[2])})
se_report_filtered is a function that actually calculates new values for me and returns a list.
Then use test to populate all of the other output values. I can't seem to get that to work. Instead, I cam calling se_report_filtered for each of my outputs. This seems like the wrong approach.
This is not a fully reproducible snippet but I am hoping the idea comes across still.
library(shiny)
library(shinydashboard)
header <- dashboardHeader(title = "Home")
frow1 <- fluidRow(
valueBoxOutput("value2"),
)
body <- dashboardBody(frow1)
#completing the ui part with dashboardPage
ui <- dashboardPage(title = 'Review', header, sidebar, body, skin='red')
server <- function(input, output) {
output$value2 <- renderValueBox({
valueBox(
formatC(se_report_filtered(my_filter = input$PM_ID,
start_year = input$obs[1],
end_year = input$obs[2])[[2]],
format="d", big.mark=',')
,'Total Met'
,icon = icon("stats",lib='glyphicon')
,color = "green")
})
}
shinyApp(ui, server)
So, essentially, I want to replace:
output$value2 <- renderValueBox({
valueBox(
formatC(se_report_filtered(my_filter = input$PM_ID,
start_year = input$obs[1],
end_year = input$obs[2])[[2]],
format="d", big.mark=',')
,'Total Met'
,icon = icon("stats",lib='glyphicon')
,color = "green")
})
with
output$value2 <- renderValueBox({
valueBox(
formatC(test[[2]],
format="d", big.mark=',')
,'Total Met'
,icon = icon("stats",lib='glyphicon')
,color = "green")
})
I believe I am missing something fundamental when it comes to dealing with reactive variables.
Again I am not sure what your function does so I am creating a reactive list with the fourth element being an input from a slider. When I call the reactive variable I assign it to a regular variable before sub-setting the fourth out. This is all done within the render function.
library(shiny)
library(shinydashboard)
ui <- fluidPage(
fluidRow(
valueBoxOutput("value2"),
sliderInput("slider","Fourth Element", 1, 10, 5)
))
server <- function(input, output, session) {
test<-reactive(list(1,2,3,input$slider))
output$value2 <- renderValueBox({
Test<-test()
Test<-Test[4]
valueBox(
formatC(Test,
format="d", big.mark=',')
,'Total Met'
,icon = icon("stats",lib='glyphicon')
,color = "green")
})
}
shinyApp(ui = ui, server = server)
Since the render function is a reactive environment, it responds to changes in changes to reactive variables, in this case test()
.
In your case test() returns whatever is created inside of se_report_filtered
, it can be subset the same way.