3

我一直在尝试找到一个解决方案,如何使用闪亮的按钮添加和删除输入字段。我没有源代码,因为我没有取得太大进展,但是这个 jQuery 示例(http://www.mkyong.com/jquery/how-to-add-remove-textbox-dynamically-with-jquery / ) 很好地了解了我要完成的工作。这可能是闪亮的还是我应该使用闪亮的js来做到这一点?先感谢您!

4

2 回答 2

7

EDIT: I read the jQuery example a bit more, and added a code snippet doing what I think you were looking for.

I don't know jQuery, so I couldn't make much out of the example link. I took a guess on what you wanted, but I think the key idea is the use of renderUI and uiOutput even if my suggestion here misses the point.

To toggle a ui element:

If you specifically don't want to use shinyjs, you could do something like this:

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)

To add and remove elements:

After reading a bit of the jQuery example, I think this is similar to what you were looking for:

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)

The problem with this approach is that each time you press the add or remove button, all of the input boxes get re-rendered. This means that any input you might have had on them disappears.

I think you could get around that by also saving the current input values of the input boxes into a reactiveValues object, and setting the values from the object as the starting values of the re-rendered input boxes by using the value option in textInput. I'll leave the implementation of that for now, though.

于 2015-07-16T14:29:04.687 回答
4

谢谢@Mikko Marttila 的回答。我能够将它用于我的目的。另外,关于所有输入框在此处重新呈现的问题,我发现从这个答案中可以找到一个解决方案。您可以使用 保存所有用户输入,然后相应地调用反应列表以将每个值设置为语句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()因为当您尝试在该字段中键入时重新渲染框时会很烦人

于 2019-06-05T22:35:26.900 回答