Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use conditional panel in R Shiny to only hide and show user inputs while still allowing underlying calculations to run?

Tags:

r

shiny

In the below R Shiny code, I am using a conditionalPanel() to show/hide optional user inputs into "child X/Y tables" for including additional variables into mathematical operations. I only want the conditionalPanel() to hide (and show) additional user inputs, into the child X/Y tables that render in the sidebarPanel(), while allowing the calculations to run as if these user inputs were not hidden and thus render in the mainPanel() the output table called mainTbl regardless of whether or not the checkboxInput() is checked. How can this be done?

These images explain. This first image is what appears when the App is first invoked: enter image description here

And this image shows what renders when the checkboxInput() is checked. I would like the below output table from the mainPanel() to render even when the checkboxInput() is not checked, when first invoking the App: enter image description here

Code:

library(shiny)
library(rhandsontable)

extraFun <- function(input_df, time_win, col_name) {
  df <- setNames(data.frame(rep(NA, time_win)), col_name)
  df[,col_name] <- 
    ifelse(seq_along(df[,1])%in%input_df[,1],input_df[match(seq_along(df[,1]),input_df[,1]),2],0)
  return(df)
}

ui <- fluidPage(
  sidebarPanel(
    h5(strong("Variable (Y) over window (W):")),
    rHandsontableOutput("parentTbl"), 
    checkboxInput("showCurves", HTML("<b>Add curves</b>"), FALSE),  
    conditionalPanel(
      condition = "input.showCurves == true",
      uiOutput("childTbl")
    )
  ),
  mainPanel(tableOutput("mainTbl"))
)

server <- function(input, output, session) {
  parentVars  <- lapply(1:2, function(i) { reactiveValues(data = 2) })
  grpInputs   <- reactiveValues(tables = list())
  plus        <- reactive(extraFun(grpInputs$tbl[["A"]],10,"A"))
  minus       <- reactive(extraFun(grpInputs$tbl[["B"]],10,"B"))
  
  output$parentTbl <- renderRHandsontable({
    rhandsontable(
      data.frame(Inputs = sapply(parentVars, function(x) x$data)),
      rowHeaders = c("A","B")
    )
  })
  
  observeEvent(input$parentTbl, {
    newValues <- hot_to_r(input$parentTbl)$Inputs
    for (i in 1:2) {parentVars[[i]]$data <- newValues[i]}
  })
 
  # Below builds child X/Y tables #
  lapply(1:2, function(i) {
    varInputId <- c("A","B")[i]
    output[[varInputId]] <- renderRHandsontable({
      df <- data.frame(X = 1, Y = parentVars[[i]]$data)
      rhandsontable(df, contextMenu = TRUE, rowHeaders = FALSE) 
    })
  })
  
  output$childTbl <- renderUI({
    lapply(1:2, function(i) {
      varInputId <- c("A","B")[i]
      list(
        h5(strong(paste("Adjust ", varInputId, " (Y) at time X:"))),
        rHandsontableOutput(varInputId)
      )
    })
  })
  
  observe({
    lapply(1:2, function(i) {
      varInputId <- c("A","B")[i]
      if (!is.null(input[[varInputId]])) {
        grpInputs$tbl[[i]] <- hot_to_r(input[[varInputId]])
        names(grpInputs$tbl)[i] <- varInputId
      }
    })
  })
  
  amCrs <- reactive({
    balances <- cumprod(c(1, 1+plus()[1:10,1]-minus()[1:10,1]))
    b <- head(balances, -1)
    result <- data.frame(
      Begin=b,Add=b*plus()[1:10,1],Subtract=b*minus()[1:10,1],End=balances[-1]
    )
  })
  
  output$mainTbl <- renderTable({
    req(length(grpInputs$tbl) > 0)
    amCrs()
  })
  
}

shinyApp(ui, server)
like image 725
Village.Idyot Avatar asked Oct 23 '25 15:10

Village.Idyot


1 Answers

Add outputOptions(output, varInputId, suspendWhenHidden = FALSE) here:

  lapply(1:2, function(i) {
    varInputId <- c("A","B")[i]
    output[[varInputId]] <- renderRHandsontable({
      df <- data.frame(X = 1, Y = parentVars[[i]]$data)
      rhandsontable(df, contextMenu = TRUE, rowHeaders = FALSE) 
    })
    outputOptions(output, varInputId, suspendWhenHidden = FALSE)
  })
like image 99
Stéphane Laurent Avatar answered Oct 26 '25 06:10

Stéphane Laurent