使用actionButtons基于索引动态添加和删除uiOutput元素

Ore*_*lis 5 r shiny

我正在尝试uiOutput使用索引来添加和删除元素,以跟踪每个单独的元素。列表中有一个actionButton用于添加和的元素,每个元素都有一个x按钮,用于删除所选项目,如下图所示:

闪亮的动态元素示例

我正在使用同时包含uiserver代码的单个.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调用工作(这似乎是我不了解的范围界定问题)。由于事先不知道元素的数量,因此这些值对我不起作用。有人知道如何进行这项工作吗?谢谢。

K. *_*hde 5

我为您提供了一个修复程序,这在后端可能不美观,但使生活变得非常轻松。我建议您将所有元素嵌套在一起。使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)