闪亮:如何将从renderUI生成的“反应性输入”作为函数中的输入?

时间:2019-03-29 10:10:00

标签: r shiny shinydashboard shiny-reactivity

简介

我正在做一个Shiny应用程序(仪表板)以完成一些工作。我有一个名称数据框(从外部Excel文件生成,该扩展名可能会扩展,因此需要反应性),它应该为上述每个名称生成一个collapsePanel(来自bsCollapse)提到的清单。这已经在服务器中使用renderUI来实现和运行;但是,现在我实际上希望能够更改collapsePanel中包含的内容的输入:面板中有几个输入,但是最重要的是,在此示例中将显示的是一个复选框组。我想在功能中使用复选框组的输入时出现问题(例如,保存新信息)。

最小工作示例

if (!require("pacman")) install.packages("pacman")

pacman::p_load(tidyverse, shiny, shinythemes, sweetalertR, shinyWidgets, 
shinycssloaders, shinyBS, shinyjs, shinydashboard, rlist, readxl)

list_of_names <- tibble("Name" = c("Name1", "Name2", "Name3"), 
    "0 pt" = c("Criteria 0 name1", "Criteria 0 name2", "Criteria 0 name3"), 
    "1 pt" = c("Criteria 1 name1", "Criteria 1 name2", "Criteria 1 name3"), 
    "2 pt" = c("Criteria 2 name1", "Criteria 2 name2", "Criteria 2 name3"))

t <- c()
for (i in list_of_names$Name) {
    t <- c(t, paste0("input$", i, "_id"))
}

mycollapse <- lapply(1:nrow(list_of_names), function(i) {
    bsCollapsePanel(paste0(list_of_names$Name[i]),
    awesomeCheckboxGroup(inputId = paste0(list_of_names$Name[i], "_id"),label = NULL,
    choices = as.character(list_of_names[i,2:4]),
    status = "success", width = "75%"))
})
mycollapse[["id"]] <- "collapseID"
mycollapse[["multiple"]] <- FALSE
mycollapse[["open"]] <- "Name1"

#### UI ----------

ui <- dashboardPage(
  dashboardHeader(title = "Minimal Example"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Dashboard", tabName = "Dashboard", icon = icon("dashboard"), 
               selected = TRUE))),   
  dashboardBody(
      fluidPage(
          column(6, shinyjs::useShinyjs(), withSpinner(uiOutput("Data"))))))

server <- function(input, output, session) {
    output$Data <- renderUI({
        tagList(
            do.call(bsCollapse, args = mycollapse) %>% return(),
            actionButton("Save", "Save"))
    })

    observeEvent(input$Save, {
        confirmSweetAlert(session, inputId = "Save_SWAL", title = 
        "Save?", text = "Are you sure?",
        type = "warning", danger_mode = TRUE, btn_labels = c("Cancel", "Yes, save please"))
    })

    observeEvent(input$Save_SWAL, {
        if (isTRUE(input$Save_SWAL)) {
            # SOMETHING HERE
        }
    })
}

shinyApp(ui, server)

问题

我的问题是,现在我想在函数中使用input$Name1_idinput$Name2_idinput$Name3_id并在代码中说“ SOMETHING HERE”,例如转换得分当我单击操作按钮时选择最大和最小值。

所以基本上我想要的是以下内容,但以一种反应方式:

observeEvent(input$Save_SWAL, {
    if (isTRUE(input$Save_SWAL)) {
        list(
            "Result1" = list("min" = min(input$Name1_id), "max" = max(input$Name1_id)), 
            "Result2" = list("min" = min(input$Name2_id), "max" = max(input$Name2_id)),
            "Result3" = list("min" = min(input$Name3_id), "max" = max(input$Name3_id))
        ) %>% print()
    }
})

如何使用for循环并应用?

我尝试在字符串上使用eval()do.call(),例如:"input$Name1_id";但是这些选项似乎都无法解决问题。

observeEvent(input$Save_SWAL, {
    if (isTRUE(input$Save_SWAL)) {
        sapply(do.call(t), min) %>% print()
    }
})

1 个答案:

答案 0 :(得分:0)

@Morten,我对sapply不太了解,但我想尝试一下。 2小时后,我无法从sa p层结构中获得任何有用的信息,但确实为您提供了2种替代解决方案。下面的代码在注释中有一些解释

我遇到sapply的问题是我得到了list()或打印的inputs的名称而不是它们的values。 通常,我会使用eval(parse(text = 'name of input here'))来处理以字符串而不是代码形式表示的输入名称,但是对于在apply函数内部使用它的这种情况,我似乎无法理解为什么它不起作用。

无论如何,下面是一种对输入名称使用lapply或通过将结果收集在reactiveVariable中的方法,即,一个列表包含您所有{每组{1}}。

T/F values