我正在尝试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({})
})
})
Run Code Online (Sandbox Code Playgroud)
当我将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({})
})
Run Code Online (Sandbox Code Playgroud)
我无法进行for循环或lapply调用工作(这似乎是我不了解的范围界定问题)。由于事先不知道元素的数量,因此这些值对我不起作用。有人知道如何进行这项工作吗?谢谢。
我为您提供了一个修复程序,这在后端可能不美观,但使生活变得非常轻松。我建议您将所有元素嵌套在一起。使uiOutput数字i包含uiOutput下一个。这样,您可以连续添加它们,而无需担心元素的大小或总数。性能方面这也没关系,特别是因为我认为您不会创建数千个过滤器。有关更多详细信息,请参阅代码。
对于删除,您已经看到跟踪所有按钮输入值很乏味。所以我建议你设计一个变量来观察,它告诉你被点击的元素编号。我们可以通过onclick按钮的自定义函数来实现这一点,将按钮编号发送到一个单一的输入变量。您可能想让自己熟悉 JavaScript 客户端函数Shiny.onInputChange。简单地说:它在给定的变量名下向 R 后端发送一个值。
删除相应的 ui 元素很容易。
如果您想深入了解并设计更清晰、更精细的解决方案,请尝试此页面和相关问题。在那里,您可以获得有关如何设计动态 ui 块并将其添加到文档中的意见,而无需使用常用的单个uiOutput包装器。
下面的代码(我做了一个普通的 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)
Run Code Online (Sandbox Code Playgroud)