【问题标题】:Display the selected choice of a dynamically generated 'selectizeInput' widget based on the selected choice of previous widget根据先前小部件的选定选项显示动态生成的“selectizeInput”小部件的选定选项
【发布时间】:2019-12-12 20:26:09
【问题描述】:

我正在尝试构建一个闪亮的应用程序,该应用程序在用户按下“+”按钮时生成具有多个 selectInput 或 selectizeInput 小部件的行,并在他按下“-”按钮时删除这些行。下图展示了我现在所取得的成就:

我闪亮的应用现在的样子:https://imgur.com/uQfdJrv

我的问题是我找不到一种方法来显示新行中的小部件与前一行中小部件的选定值相同。事实上,用户可能只想更改某些输入的值,而不要触及其他输入的值。

参考上图,假设用户在第一次测试中选择“Amikacin”作为抗生素,选择“5”作为 AMR。第二个测试总是用“Amikacin”,但他的 AMR 值为 10。新的输入,在按下“+”按钮后,必须立即显示“Amikacin”和“5”,之后用户只需更改“10”中第二行的“5”。

这是我使用的代码:


library(shiny)
library(shinyjs)

###= UI
ui <- fluidPage(

br(),

useShinyjs(),

  fluidRow(
    column(width = 12,
           actionButton(inputId = "add_amr_test",
                        label = icon(name = "plus",
                                     lib = "font-awesome")),
           actionButton(inputId = "remove_amr_test",
                        label = icon(name = "minus",
                                     lib = "font-awesome")),
           div(style = "display: inline-block;
                        padding: 0px 10px;",
               h5("Add or remove an antimicrobial resistance test")),
           tags$div(id = "amr_test_placeholder")
    )
  ),

br()

)

###= SERVER
server <- function(input, output, session) {

  Antibiotics_name <- c("", "Amikacin", "Ampicillin", "Tetracycline")

  observe({

    toggleState(id = "remove_amr_test",
                condition = input$add_amr_test > input$remove_amr_test)

  })

  amr_test_values <- reactiveValues(val = 0)

  ###= Add ui
  observeEvent(input$add_amr_test, {

    amr_test_divId <- length(amr_test_values$val) + 1

    insertUI(
      selector = "#amr_test_placeholder",
      where = "beforeBegin",
      ui = tags$div(
        id = amr_test_divId,
        fluidRow(

          br(),

          column(width = 3,
                 selectizeInput(inputId = paste0("drug_",
                                                 input$add_amr_test - input$remove_amr_test),
                                label = h5(paste0("Antibiotic ",
                                                  input$add_amr_test - input$remove_amr_test)),
                                choices = Antibiotics_name,
                                selected = "")
          ),
          column(width = 1,
                 selectizeInput(inputId = paste0("rescom_",
                                                 input$add_amr_test - input$remove_amr_test),
                                label = h5(paste0("AMR ",
                                                  input$add_amr_test - input$remove_amr_test)),
                                choices = c("",
                                            seq(from = 1,
                                                to = 100,
                                                by = 1)),
                                selected = "")
          )
        )
      )
    )

    amr_test_values$val <- c(amr_test_values$val,
                             amr_test_divId)

  })

  ###= Remove ui
  observeEvent(input$remove_amr_test, {

    removeUI(

      selector = paste0('#', amr_test_values$val[length(amr_test_values$val)])

    )

    amr_test_values$val <- amr_test_values$val[-length(amr_test_values$val)]

  })

}



###= RUN APP
shinyApp(ui = ui, server = server)

最后,这是用户按下“+”按钮生成第二行小部件后得到的预期结果的图像。

预期结果示例:https://imgur.com/NIpOZOE

最后一个问题:一旦用户的每个小部件都有一个特定的值,那么将所有这些值存储在数据框中的最佳方式是什么?

非常感谢。

【问题讨论】:

标签: r input shiny reactive shinyapps


【解决方案1】:

第一个问题请见下文:

library(shiny)
library(shinyjs)

###= UI
ui <- fluidPage(

br(),

useShinyjs(),

  fluidRow(
    column(width = 12,
           actionButton(inputId = "add_amr_test",
                        label = icon(name = "plus",
                                     lib = "font-awesome")),
           actionButton(inputId = "remove_amr_test",
                        label = icon(name = "minus",
                                     lib = "font-awesome")),
           div(style = "display: inline-block;
                        padding: 0px 10px;",
               h5("Add or remove an antimicrobial resistance test")),
           tags$div(id = "amr_test_placeholder")
    )
  ),

br()

)

###= SERVER
server <- function(input, output, session) {

  Antibiotics_name <- c("", "Amikacin", "Ampicillin", "Tetracycline")

  observe({

    toggleState(id = "remove_amr_test",
                condition = input$add_amr_test > input$remove_amr_test)

  })

  amr_test_values <- reactiveValues(val = 0)

  ###= Add ui
  observeEvent(input$add_amr_test, {

    amr_test_divId <- length(amr_test_values$val) + 1

    # Simplified input_number here and code to obtain previous values if they exist
    input_number <- input$add_amr_test - input$remove_amr_test
    if (!is.null(eval(parse(text = paste0("input$drug_", input_number - 1))))) {
        drug_value = eval(parse(text = paste0("input$drug_", input_number - 1)))
    } else {
        drug_value = ""
    }
    if (!is.null(eval(parse(text = paste0("input$rescom_", input_number - 1))))) {
        rescom_value = eval(parse(text = paste0("input$rescom_", input_number - 1)))
    } else {
        rescom_value = ""
    }

    insertUI(
      selector = "#amr_test_placeholder",
      where = "beforeBegin",
      ui = tags$div(
        id = amr_test_divId,
        fluidRow(

          br(),

          column(width = 3,
                 selectizeInput(inputId = paste0("drug_",
                                                 input_number),
                                label = h5(paste0("Antibiotic ",
                                                  input_number)),
                                choices = Antibiotics_name,
                                selected = drug_value)
          ),
          column(width = 1,
                 selectizeInput(inputId = paste0("rescom_",
                                                 input_number),
                                label = h5(paste0("AMR ",
                                                  input_number)),
                                choices = c("",
                                            seq(from = 1,
                                                to = 100,
                                                by = 1)),
                                selected = rescom_value)
          )
        )
      )
    )

    amr_test_values$val <- c(amr_test_values$val,
                             amr_test_divId)

  })

  ###= Remove ui
  observeEvent(input$remove_amr_test, {

    removeUI(

      selector = paste0('#', amr_test_values$val[length(amr_test_values$val)])

    )

    amr_test_values$val <- amr_test_values$val[-length(amr_test_values$val)]

  })

}



###= RUN APP
shinyApp(ui = ui, server = server)

【讨论】:

  • Eli Berkow,非常感谢您的及时响应以及您简单、优雅且非常智能的解决方案,它完全可以正常工作。希望这对其他人也有帮助。关于我的第二个问题,然后我通过将sapply 应用于我以这种方式获得输入的每个变量,将数据存储在数据框中:input[[paste0("variable_", i)]]
  • 我很高兴它成功了。这听起来像是一种存储数据的聪明方法。我看了一会儿这个问题,但尝试跟踪输入和所有更新似乎相当复杂。
  • Eli,就像您创建不同的 inputIds 一样,用一些 css 自定义新小部件的最佳方法是什么?例如,对于我尝试添加(在顶部)的“drug_i”的 selectizeInputs,此代码:tags$style(paste0("#animal_species_", input_number(), " {font-size:1px; width:200px; height:5px;}")),但它似乎不起作用。我不能为每个小部件指定一个通用标签,因为它们应该不同。再次感谢。
  • 这是一个完全不同的问题,可能值得在 SO 上单独创建。请给我确切的要求。药物必须不同于rescom吗?个别药物/救援?
  • Eli,对于我之前的评论,我犯了一个错误,将 amr_div ID 放在引号中(“amr_test_divId”),因此删除按钮不再起作用。你的解决方案很棒。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2011-01-14
  • 2020-06-10
  • 1970-01-01
  • 1970-01-01
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多