我正在尝试使用索引添加和删除uiOutput
元素以跟踪每个元素。列表中有actionButton
个添加元素,删除所选项目的每个元素都有一个 x 按钮,如下图所示:
我正在使用包含ui
和server
代码的单个.Rmd文件。我目前的解决方案(我无法生成上面显示的所需功能---它基本上什么都不做)如下:
actionButton("addFilter", "Add filter", icon=icon("plus", class=NULL, lib="font-awesome"))
i <- 0
observeEvent(input$addFilter, {
i <<- i + 1
uiOutput(paste("filterPage",i,sep=""))
output[[paste("filterPage",i,sep="")]] = renderUI({
fluidPage(
fluidRow(
column(6, selectInput(paste("filteringFactor",i,sep=""), "Choose factor to filter by:",
choices=c("factor A", "factor B", "factor C"), selected="factor B",
width="100%")),
column(6, actionButton(paste("removeFactor",i,sep=""), "",
icon=icon("times", class = NULL, lib = "font-awesome")))
)
)
})
observeEvent(input[[paste("removeFactor",i,sep="")]], {
output[[paste("filterPage",i,sep="")]] = renderUI({})
})
})
当我将uiOutput
和删除按钮observeEvent
放在添加按钮observeEvent
之外时代码可以正常工作,但我需要为每个索引创建一个单独的语句,如下所示:
uiOutput(paste("filterPage",1,sep=""))
uiOutput(paste("filterPage",2,sep=""))
uiOutput(paste("filterPage",3,sep=""))
uiOutput(paste("filterPage",4,sep=""))
actionButton("addFilter", "Add filter", icon=icon("plus", class=NULL, lib="font-awesome"))
i <- 0
observeEvent(input$addFilter, {
i <<- i + 1
output[[paste("filterPage",i,sep="")]] = renderUI({
fluidPage(
fluidRow(
column(6, selectInput(paste("filteringFactor",i,sep=""), "Choose factor to filter by:",
choices=c("factor A", "factor B", "factor C"), selected="factor B",
width="100%")),
column(6, actionButton(paste("removeFactor",i,sep=""), "",
icon=icon("times", class = NULL, lib = "font-awesome")))
)
)
})
})
observeEvent(input[[paste("removeFactor",1,sep="")]], {
output[[paste("filterPage",1,sep="")]] = renderUI({})
})
observeEvent(input[[paste("removeFactor",2,sep="")]], {
output[[paste("filterPage",2,sep="")]] = renderUI({})
})
observeEvent(input[[paste("removeFactor",3,sep="")]], {
output[[paste("filterPage",3,sep="")]] = renderUI({})
})
observeEvent(input[[paste("removeFactor",4,sep="")]], {
output[[paste("filterPage",4,sep="")]] = renderUI({})
})
我无法进行for循环或lapply
调用工作(它看起来像我不明白的范围问题)。由于事先不知道元素的数量,硬编码值对我来说不起作用。有人知道如何使这项工作?谢谢。
答案 0 :(得分:4)
我有一个适合你的方法,在后端可能不漂亮,但让生活变得轻松。我建议你将所有元素嵌套在一起。使uiOutput
号码i
包含下一个uiOutput
。这样,您可以连续添加它们,而无需担心元素的大小或总数。性能方面,这也没关系,特别是因为我不认为你创造了数以千计的过滤器。有关更多详细信息,请参阅代码。
对于删除,您已经看到跟踪所有按钮输入值很繁琐。因此,我建议您设计一个要观察的变量,它会告诉您已单击的元素编号。我们可以使用自定义onclick
函数为我们的按钮实现此功能,将按钮编号发送到一个输入变量。您可能希望熟悉JavaScript客户端函数Shiny.onInputChange
。简单地说:它在给定变量名下的R后端发送一个值。
删除相应的ui元素很简单。
如果您想了解更多内容并设计更清晰,更精细的解决方案,请尝试this page及相关问题。在那里,您可以获得有关如何在没有常用的单uiOutput
包装器的情况下设计和添加动态ui块的输入。
下面的代码(我制作了一个常规的ui-server应用程序):
library(shiny)
ui <- shinyUI(
fluidPage(
actionButton("addFilter", "Add filter", icon=icon("plus", class=NULL, lib="font-awesome")),
uiOutput("filterPage1")
)
)
server <- function(input, output){
i <- 0
observeEvent(input$addFilter, {
i <<- i + 1
output[[paste("filterPage",i,sep="")]] = renderUI({
list(
fluidPage(
fluidRow(
column(6, selectInput(paste("filteringFactor",i,sep=""), "Choose factor to filter by:",
choices=c("factor A", "factor B", "factor C"), selected="factor B",
width="100%")),
column(6, actionButton(paste("removeFactor",i,sep=""), "",
icon=icon("times", class = NULL, lib = "font-awesome"),
onclick = paste0("Shiny.onInputChange('remove', ", i, ")")))
)
),
uiOutput(paste("filterPage",i + 1,sep=""))
)
})
})
observeEvent(input$remove, {
i <- input$remove
output[[paste("filterPage",i,sep="")]] <- renderUI({uiOutput(paste("filterPage",i + 1,sep=""))})
})
}
shinyApp(ui, server)
答案 1 :(得分:0)
此链接可以帮助您吗?
http://shiny.rstudio.com/gallery/creating-a-ui-from-a-loop.html
可能无法保持uiOutput
元素的数量动态,但您希望在实践中出现多少元素?您是否可以创建10个或20个并在按下按钮时打开和关闭它们?