R Shiny Dashboard在初始化

时间:2017-03-28 22:14:03

标签: r user-interface shiny shinydashboard

我正在尝试根据用户希望提供输入的方式生成动态UI元素。我使用Shiny Dashboard是为了简单,但我遇到了sidebarMenu的问题。以前当我将静态UI元素直接放入sidebarMenu时,我没有任何问题,但是当我尝试将动态UI元素放入sidebarMenu时,我遇到了问题。我使用的是R 3.3.2和Shiny 1.0.0以及Dashboard 0.5.3。

我遇到的具体问题是,当程序首次加载时,动态UI元素不会加载。代码中似乎没有任何延迟,因为即使在卸载动态UI时,界面的所有功能也能正常工作。通过选择导航栏中的一个选项卡,或者将鼠标悬停在我已实现工具提示的内容上,我可以加载动态UI。

我无法提供确切的代码,但我重新创建了一个小得多的可重现的示例,它具有与我的大版本相同的所有问题。

library("shiny")
library("shinydashboard")

header = dashboardHeader(
    title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
    sidebarMenu(
        menuItemOutput("dynamic_sidebar")
    )
)
body = dashboardBody(
    tabBox(
        tabPanel(
            strong("One")
        ),
        tabPanel(
            strong("Two")
        )
    )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){
output$dynamic_sidebar = renderMenu({
        sidebarMenu(
            menuItem(
                "Slider or numeric problem",
                radioButtons("slider_or_numeric",
                   label = "Slider or Numeric Input",
                   choices = c("Slider", "Numeric"),
                   selected = "Slider",
                   inline = TRUE
                ),
                uiOutput("input")
            )     
        )
    })
    output$input = renderUI({
        if (input$slider_or_numeric == "Slider"){
            sliderInput("slider", 
                label = "slider",
                min = 0, max = 1,
                value = 0
            )
        } else {
            numericInput("numeric", 
                label = "numeric",
                min = 0, max = 1,
                value = 0
            )
        }
    })
})

shinyApp(ui, server)

要验证问题,在加载后只需打开菜单项,您就会看到单选按钮,但没有别的。将导航栏上的选项卡从一个切换为两个,输入应显示在菜单中(必须在菜单打开时完成)。

我真的只是抓住稻草,我已经对它进行了几个小时的故障排除,我认为这只是与这些功能不兼容。我真的希望有人可以证明我错了,并告诉我,我只是做错了。我已经为我的主程序找到了替代方案,但它们与我在这里要完成的工作没有相同的美学。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我想我发现了这个问题,这很棘手,并且花了一些时间才找到它。虽然这是一个很小的变化,但我会发布整个事情。

我认为这就是你想要的:

library("shiny")
library("shinydashboard")

header = dashboardHeader(
  title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
  sidebarMenu(
    menuItemOutput("dynamic_sidebar")
  )
)
body = dashboardBody(
  tabBox(
    tabPanel(
      strong("One")
    ),
    tabPanel(
      strong("Two")
    )
  )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){
  output$dynamic_sidebar = renderMenu({
    sidebarMenu(
      menuItem(
        "Slider or numeric problem",
        radioButtons("slider_or_numeric",
                     label = "Slider or Numeric Input",
                     choices = c("Slider", "Numeric"),
                     selected = "Slider",
                     inline = TRUE
        )
      ),   
      uiOutput("input")  # no longer in menuItem call
    )
  })
  output$input = renderUI({
    if (input$slider_or_numeric == "Slider"){
      sliderInput("slider", 
                  label = "slider",
                  min = 0, max = 1,
                  value = 0
      )
    } else {
      numericInput("numeric", 
                   label = "numeric",
                   min = 0, max = 1,
                   value = 0
      )
    }
  })
})
shinyApp(ui, server)

我认为问题是uiOutput("input")以某种方式进入了menuItem电话。这是Shiny的危害,而且Shiny编辑显然需要更多的支持来展示这种范围。

坦率地说,当你玩弄它时,我有点疑惑它为何会出现。但够了......

虽然我不完全确定我理解你希望如何使用它(显然它只是一个玩具示例),但这就是它在启动时的样子:

enter image description here

此后菜单扩展并通过新曝光的单选按钮控件更改输入类型。

enter image description here

答案 1 :(得分:1)

所以我找到了另一个SO帖子的解决方案:r shiny - uiOutput not rendering inside menuItem我感到有点惭愧我没有在第一组搜索工作中找到这个。为了更详细地总结帖子所说的内容,我在menuItem中呈现的UI元素被初始化为隐藏,默认情况下隐藏了隐藏的项目。作为帖子详细信息,您可以通过outputOptions函数更改此选项。这是一个更新版本,完全按照我原来的要求运行:

library("shiny")
library("shinydashboard")

header = dashboardHeader(
    title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
    sidebarMenu(
        menuItemOutput("dynamic_sidebar")
    )
)
body = dashboardBody(
    tabBox(
        tabPanel(
            strong("One")
        ),
        tabPanel(
            strong("Two")
        )
    )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){

    output$input <- renderUI({})
    outputOptions(output, "input", suspendWhenHidden = FALSE)

output$dynamic_sidebar = renderMenu({
        sidebarMenu(
            menuItem(
                "Slider or numeric problem",
                radioButtons("slider_or_numeric",
                   label = "Slider or Numeric Input",
                   choices = c("Slider", "Numeric"),
                   selected = "Slider",
                   inline = TRUE
                ),
                uiOutput("input")
            )     
        )
    })
    output$input = renderUI({
        if (input$slider_or_numeric == "Slider"){
            sliderInput("slider", 
                label = "slider",
                min = 0, max = 1,
                value = 0
            )
        } else {
            numericInput("numeric", 
                label = "numeric",
                min = 0, max = 1,
                value = 0
            )
        }
    })
})

shinyApp(ui, server)

请注意,在设置输出对象之前必须先对其进行初始化,否则它将为null并导致错误。

感谢Mike试图回答这个问题,希望如果其他人偶然发现这个问题,他们会发现这个解决方案很有用。