R Shiny: How to dynamically append arbitrary number of input widgets

后端 未结 4 559
没有蜡笔的小新
没有蜡笔的小新 2021-02-02 01:06

The goal

I am working on a Shiny app that allows the user to upload their own data and focus on the entire data or a subset by providing data filtering widgets describ

4条回答
  •  渐次进展
    2021-02-02 01:48

    You need to check for existing input values and use them if available:

      # Prevent dynamic inputs from resetting
      newInputValue <- "Option 1"
      if (newInputId %in% names(input)) {
        newInputValue <- input[[newInputId]]
      }
      # Define new input
      newInput <- selectInput(newInputId, newInputLabel, c("Option 1", "Option 2", "Option 3"), selected=newInputValue)
    

    A working version of the gist (without the reset problem) can be found here: https://gist.github.com/motin/0d0ed0d98fb423dbcb95c2760cda3a30

    Copied below:

    ui.R

    library(shiny)
    
    shinyUI(pageWithSidebar(
    
      # Application title
      headerPanel("Dynamically append arbitrary number of inputs"),
    
      # Sidebar with a slider input for number of bins
      sidebarPanel(
        uiOutput("allInputs"),
        actionButton("appendInput", "Append Input")
      ),
    
      # Show a plot of the generated distribution
      mainPanel(
        p("This shows how to add an arbitrary number of inputs
          without resetting the values of existing inputs each time a new input is added.
          For example, add a new input, set the new input's value to Option 2, then add
          another input. Note that the value of the first input does not reset to Option 1.")
      )
    ))
    

    server.R

    library(shiny)

    shinyServer(function(input, output) {
    
      output$allInputs <- renderUI({
        # Get value of button, which represents number of times pressed (i.e. number of inputs added)
        inputsToShow <- input$appendInput
        # Return if button not pressed yet
        if(is.null(inputsToShow) || inputsToShow < 1) return()
        # Initialize list of inputs
        inputTagList <- tagList()
        # Populate the list of inputs
        lapply(1:inputsToShow,function(i){
          # Define unique input id and label
          newInputId <- paste0("input", i)
          newInputLabel <- paste("Input", i)
          # Prevent dynamic inputs from resetting
          newInputValue <- "Option 1"
          if (newInputId %in% names(input)) {
            newInputValue <- input[[newInputId]]
          }
          # Define new input
          newInput <- selectInput(newInputId, newInputLabel, c("Option 1", "Option 2", "Option 3"), selected=newInputValue)
          # Append new input to list of existing inputs
          inputTagList <<- tagAppendChild(inputTagList, newInput)
        })
        # Return updated list of inputs
        inputTagList
      })
    
    })
    

    (The solution was guided on Nick's hints in the original gist from where you got the code of the promising solution)

提交回复
热议问题