[英]Reset input fields of dynamically generated widgets through insertUI
我正在尝试开发Shinkapp,这是更大形式的一部分。 特别是,对于此模块,用户可以动态添加(通过insertUI)和删除(通过removeUI)具有与上一个控件完全相同的新行。 此外,每个新的小部件都将包含与上一行小部件完全相同的选择,这要归功于Eli Berkow ,他找到了最后一种功能的解决方案。
理想情况下,在用户提交答案后,将shinyjs
放置在observeEvent()
中的shinyjs
包的reset()
函数来重置每个字段的输入。 这与“静态”窗口小部件(此示例中未包括)很好用,但是我找不到一种方法来重置动态生成的窗口小部件的输入字段。
我试图将每一行分配给不同的div()
并在我的observeEvent()
内部使用了for
循环来重置每个div()
内部的输入,但是只清理了一些字段。 此外,理想情况下,如果该按钮不仅可以重置字段,还可以删除用户添加的每一行并从0开始重新计算,那将是更好的选择。下面有一些代码在UI中插入了“ 重置按钮” ,但仍然没有任何功能。
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)
可以在以下链接中看到预期的结果。
谢谢!
编辑:
Eli Berkow对我先前版本问题的回答非常有效,因此我将其标记为正确。
我已经更新了代码,以了解当应用程序启动时自动显示小部件的第一行时,Eli的脚本应如何工作。 我不知道是否要修改与reactValues或最后一个watchEvent相关的内容。 因此,在此版本的脚本中,我添加了自动显示第一行的功能。 什么将适应Eli的代码?
ps:我在小部件下添加了一个反应性数据集,以实际查看值的存储方式是否正确(只需检查一下以了解脚本是否可以正常工作)。
谢谢!
见下文:
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()
)
###= SERVER
server <- function(input, output, session) {
observe({
toggleState(id = "remove_amr_test",
condition = input$add_amr_test > input$remove_amr_test + amr_test_values$reset)
toggleState(id = "reset_button",
condition = input$add_amr_test > input$remove_amr_test + amr_test_values$reset)
})
amr_test_values <- reactiveValues(val = 0,
reset = 0)
### Defined the input number to count every row
input_number <- reactive({
input_number <- input$add_amr_test - input$remove_amr_test - amr_test_values$reset
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)
})
###= 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)]
})
observeEvent(input$reset_button, {
for(remove_value in 2:max(amr_test_values$val)) {
removeUI(
selector = paste0('#', remove_value)
)
}
amr_test_values$reset <- input$add_amr_test - input$remove_amr_test
amr_test_values$val <- 0
})
}
###= Launch App
shinyApp(ui = ui, server = server)
我在这里添加了一个reset
反应值:
observe({
toggleState(id = "remove_amr_test",
condition = input$add_amr_test > input$remove_amr_test + amr_test_values$reset)
toggleState(id = "reset_button",
condition = input$add_amr_test > input$remove_amr_test + amr_test_values$reset)
})
amr_test_values <- reactiveValues(val = 0,
reset = 0)
### Defined the input number to count every row
input_number <- reactive({
input_number <- input$add_amr_test - input$remove_amr_test - amr_test_values$reset
return(input_number)
})
然后这个observeEvent
:
observeEvent(input$reset_button, {
for(remove_value in 2:max(amr_test_values$val)) {
removeUI(
selector = paste0('#', remove_value)
)
}
amr_test_values$reset <- input$add_amr_test - input$remove_amr_test
amr_test_values$val <- 0
})
更新资料
根据您的编辑。
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$reset)
toggleState(id = "reset_button",
condition = input$add_amr_test > input$remove_amr_test + amr_test_values$reset)
})
amr_test_values <- reactiveValues(val = 0,
reset = 0)
### Defined the input number to count every row
input_number <- reactive({
input_number <- input$add_amr_test - input$remove_amr_test - amr_test_values$reset + 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 = "A"
}
###= 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 = 1
}
###= 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)]
})
observeEvent(input$reset_button, {
for(remove_value in 3:max(amr_test_values$val)) {
removeUI(
selector = paste0('#', remove_value)
)
}
amr_test_values$reset <- input$add_amr_test - input$remove_amr_test
amr_test_values$val <- c(0, 2)
})
###= Dataset to check the dynamic updates of the responses
response <- reactive({
if (input_number() != 0 & !is.null(input[[paste0("letters_", input_number())]])) {
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.