如何通过闪亮的按钮动态添加/删除输入字段

时间:2015-07-16 12:29:06

标签: dynamic input shiny shinyjs

我一直试图找到一个解决方案,如何使用闪亮的按钮添加和删除输入字段。我没有源代码,因为我没有取得那么大的进展,但是这个jQuery示例(http://www.mkyong.com/jquery/how-to-add-remove-textbox-dynamically-with-jquery/)给出了我想要完成的内容的一个好主意。这可能是闪亮的还是我应该使用shinyjs来做到这一点?提前谢谢!

2 个答案:

答案 0 :(得分:4)

编辑:我更多地阅读了jQuery示例,并添加了我认为您正在寻找的代码段。

我不知道jQuery,所以我无法从示例链接中做出太多贡献。我猜测了你想要什么,但我认为关键的想法是使用renderUIuiOutput即使我的建议在这里错过了这一点。

要切换ui元素:

如果你特别不想使用shinyjs,你可以这样做:

library(shiny)

ui <- shinyUI(fluidPage(

  actionButton("btn", "Toggle Textbox"),

  textOutput("btn_val"),
  uiOutput("textbox_ui")

))

server <- shinyServer(function(input, output, session) {

  output$btn_val <- renderPrint(print(input$btn))

  textboxToggle <- reactive({

    if (input$btn %% 2 == 1) {
      textInput("textin", "Write something:", value = "Hello World!")
    }

  })

  output$textbox_ui <- renderUI({ textboxToggle() })

})

shinyApp(ui, server)

添加和删除元素:

在阅读了一些jQuery示例后,我认为这与您所寻找的类似:

library(shiny)

ui <- shinyUI(fluidPage(

  sidebarPanel(

      actionButton("add_btn", "Add Textbox"),
      actionButton("rm_btn", "Remove Textbox"),
      textOutput("counter")

    ),

  mainPanel(uiOutput("textbox_ui"))

))

server <- shinyServer(function(input, output, session) {

  # Track the number of input boxes to render
  counter <- reactiveValues(n = 0)

  observeEvent(input$add_btn, {counter$n <- counter$n + 1})
  observeEvent(input$rm_btn, {
    if (counter$n > 0) counter$n <- counter$n - 1
  })

  output$counter <- renderPrint(print(counter$n))

  textboxes <- reactive({

    n <- counter$n

    if (n > 0) {
      lapply(seq_len(n), function(i) {
        textInput(inputId = paste0("textin", i),
                  label = paste0("Textbox", i), value = "Hello World!")
      })
    }

  })

  output$textbox_ui <- renderUI({ textboxes() })

})

shinyApp(ui, server)

这种方法的问题是每次按下添加或删除按钮时,所有输入框都会重新渲染。这意味着您可能拥有的任何输入都会消失。

我认为你可以通过将输入框的当前输入值保存到reactiveValues对象中,并通过使用将对象中的值设置为重新渲染的输入框的起始值来解决这个问题。 value中的textInput选项。不过,我现在暂时不执行这项工作。

答案 1 :(得分:0)

谢谢@Mikko Marttila的回答。我能够将其用于我的目的。另外,在这里提到重新渲染所有输入框的问题时,我发现此answer的解决方案有效。您可以使用reactiveValuesToList()保存所有用户输入,然后相应地调用反应式列表,以在lapply()语句中将每个值设置为相应用户的输入。

library(shiny)

ui <- shinyUI(fluidPage(

  sidebarPanel(

    actionButton("add_btn", "Add Textbox"),
    actionButton("rm_btn", "Remove Textbox"),
    textOutput("counter")

  ),

  mainPanel(uiOutput("textbox_ui"))

))

server <- shinyServer(function(input, output, session) {

  # Track the number of input boxes to render
  counter <- reactiveValues(n = 0)

  # Track all user inputs
  AllInputs <- reactive({
    x <- reactiveValuesToList(input)
  })

  observeEvent(input$add_btn, {counter$n <- counter$n + 1})
  observeEvent(input$rm_btn, {
    if (counter$n > 0) counter$n <- counter$n - 1
  })

  output$counter <- renderPrint(print(counter$n))

  textboxes <- reactive({

    n <- counter$n

    if (n > 0) {
      isolate({
        lapply(seq_len(n), function(i) {
          textInput(inputId = paste0("textin", i),
                    label = paste0("Textbox", i), 
                    value = AllInputs()[[paste0("textin", i)]])
        })
      })
    }

  })

  output$textbox_ui <- renderUI({ textboxes() })

})

shinyApp(ui, server)

编辑:我将lapply()包裹在isolate()中,因为当您尝试在该字段中键入内容时,当重新渲染框时,它变得很烦人