【发布时间】:2019-08-17 11:19:23
【问题描述】:
我正在尝试开发一个闪亮的应用程序,它是更大表单的一部分。特别是,对于这个模块,用户可以动态添加(通过 insertUI)和删除(通过 removeUI)具有与前一个完全相同的小部件的新行。此外,每个新的小部件都将包含与前一行的小部件完全相同的选择,感谢Eli Berkow 找到了最后一个功能的解决方案。
理想情况下,用户提交答案后,将调用 shinyjs 包中的 reset() 函数,该函数位于 observeEvent() 中,以重置每个字段的输入。
这适用于“静态”小部件(本示例中未包含),但我找不到重置动态生成小部件的输入字段的方法。
我尝试将每一行分配给不同的div(),并在observeEvent() 中使用for 循环来重置每个div() 中存在的输入,但只清理了一些字段。此外,理想情况下,如果按钮不仅可以重置字段,还可以删除用户添加的每一行并从 0 重新开始计数。下面有一些代码,其中插入了 Reset Button用户界面,但仍然没有任何功能。
library(shiny)
library(shinyjs)
###= UI
ui <- fluidPage(
br(),
useShinyjs(),
br(),
fluidRow(
column(width = 3,
align = "center",
h5("Letters")
),
column(width = 3,
align = "center",
h5("Numbers")
)
),
br(),
fluidRow(
column(width = 12,
tags$div(id = "amr_test_placeholder")
)
),
fluidRow(
br(),
# "+" and "-" buttons
column(width = 12,
actionButton(inputId = "add_amr_test",
label = icon(name = "plus",
lib = "font-awesome")),
actionButton(inputId = "remove_amr_test",
label = icon(name = "times",
lib = "font-awesome")),
actionButton(inputId = "reset_button",
label = "RESET FIELDS")
)
),
br(),
br(),
fluidRow(
column(width = 6,
tableOutput(outputId = "show_table")
)
)
)
###= SERVER
server <- function(input, output, session) {
observe({
toggleState(id = "remove_amr_test",
condition = input$add_amr_test >= input$remove_amr_test)
})
amr_test_values <- reactiveValues(val = 0,
ignore = 0)
### Defined the input number to count every row
input_number <- reactive({
input_number <- input$add_amr_test - input$remove_amr_test + 1
return(input_number)
})
observeEvent(input$add_amr_test, {
amr_test_divId <- length(amr_test_values$val) + 1
###= Animal species
if (!is.null(eval(parse(text = paste0("input$letters_", input_number() - 1))))) {
letters_value = eval(parse(text = paste0("input$letters_", input_number() - 1)))
} else {
letters_value = ""
}
###= Animal sample type
if (!is.null(eval(parse(text = paste0("input$numbers_", input_number() - 1))))) {
numbers_value = eval(parse(text = paste0("input$numbers_", input_number() - 1)))
} else {
numbers_value = ""
}
###= Insert dynamic UI
insertUI(
selector = "#amr_test_placeholder",
where = "beforeBegin",
ui = tags$div(id = amr_test_divId,
tags$head(tags$style(HTML(".shiny-split-layout > div {overflow: visible;}"))),
br(),
fluidRow(
column(width = 3,
splitLayout(cellWidths = c("18%", "82%"),
h5(paste0(input_number(), ". ")),
selectizeInput(inputId = paste0("letters_",
input_number()),
label = NULL,
choices = c("A" = "",
"A",
"B",
"C",
"D",
"E",
"F",
"F"),
selected = letters_value,
width = "100%",
options = list(create = TRUE))
)
),
column(width = 3,
selectizeInput(inputId = paste0("numbers_",
input_number()),
label = NULL,
choices = list("1" = "",
"1" = "1",
"2" = "2",
"3" = "3",
"4" = "4",
"5" = "5"),
selected = numbers_value,
width = "100%")
)
)
)
)
amr_test_values$val <- c(amr_test_values$val,
amr_test_divId)
}, ignoreNULL = FALSE)
###= Remove dynamic 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)]
})
###= Dataset to check the dynamic updates of the responses
response <- reactive({
if (input_number() != 0) {
response <- data.frame("Letters" = sapply(X = 1:input_number(),
FUN = function(i) {
input[[paste0("letters_", i)]]
}),
"Numbers" = sapply(X = 1:input_number(),
FUN = function(i) {
input[[paste0("numbers_", i)]]
})
)
return(response)
} else {
response <- NULL
}
})
output$show_table <- renderTable({
response()
})
}
###= Launch App
shinyApp(ui = ui, server = server)
预期结果可以在以下link看到。
谢谢!
编辑:
Eli Berkow 对我之前版本的问题给出的答案非常有效,因此我将其标记为正确。
我更新了代码,以便了解当应用程序启动时自动显示第一行小部件时 Eli 的脚本应该如何工作。我不明白是否要修改与 reactiveValues 或最后一个 observeEvent 相关的内容。因此,在这个版本的脚本中,我添加了自动显示第一行的功能。什么会适应Eli的代码?
p.s.:我在小部件下添加了一个反应性数据集,以实际查看值的存储方式是否良好(只是检查脚本是否正常工作)。
谢谢!
【问题讨论】:
标签: r input shiny reset shinyjs