我正在尝试开发一个闪亮的应用程序,它是更大形式的一部分。特别是,对于此模块,用户可以动态添加(通过insertUI)和删除(通过removeUI)具有与上一个控件完全相同的新行。此外,每个新的小部件都将包含与上一行小部件完全相同的选择,这归功于Eli Berkow,因为找到了最后一种功能的解决方案。
理想地,在用户提交答案后,将调用置于reset()
内的shinyjs
包的observeEvent()
函数,以重置每个字段的输入。
可以在“静态”窗口小部件(此示例中未包括)上正常工作,但是我找不到一种方法来重置动态生成的窗口小部件的输入字段。
我尝试将每一行分配给不同的div()
,并且在for
内使用了observeEvent()
循环来重置每个div()
内的输入,但只是一些字段被清理。此外,理想情况下,如果按钮不仅可以重置字段,还可以删除用户添加的每一行并从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 <- 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的脚本应如何工作。我不知道是否要修改与reactValues或最后一个watchEvent相关的内容。因此,在此版本的脚本中,我添加了自动显示第一行的功能。什么会适应Eli的代码?
p.s .:我在小部件下添加了一个反应性数据集,以实际查看值的存储方式是否正确(只是检查以了解脚本是否工作正常)。
谢谢!
答案 0 :(得分: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()
)
###= 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)