闪亮模块无法使用renderUI

时间:2016-09-01 13:35:50

标签: r shiny

我正在使用renderUI根据用户对可视化选项的选择来选择性地呈现表格或绘图。我也使用Shiny模块在多个选项卡上显示相同的内容。虽然我已经让Shiny模块在另一个应用程序中运行得非常好,但我很难让它与renderUI一起使用。

这是我提出的一小段代码,它显示了在任一选项卡上都没有显示任何内容的问题:

myUI <- function(id) {
  ns <- NS(id)
  fluidRow(
    uiOutput(ns('myFinalText'))
  )
}

ui <- fluidPage(
  tabBox(id = 'myBox', width = 12,
         tabPanel('Tab1',
                  fluidRow(
                    myUI('tab1')
                  )),
         tabPanel('Tab2',
                  fluidRow(
                    myUI('tab2')
                  ))
         )
)

myTextFunc <- function(input, output, session, text) {
  output$myFinalText <- renderUI({
    output$myText <- renderText({text})
    textOutput('myText')
  })
}

server <- function(input, output, session) {
  callModule(myTextFunc, 'tab1', session = session, 'Hello Tab1')
  callModule(myTextFunc, 'tab2', session = session, 'Hello Tab2')
}

shinyApp(ui = ui, server = server)

关于我应该做些什么才能使这项工作的任何想法?

如下更换Shiny模块UI功能和服务器功能使其正常工作。

myUI <- function(id) {
  ns <- NS(id)
  fluidRow(
    textOutput(ns('myFinalText'))
  )
}

myTextFunc <- function(input, output, session, text) {
  output$myFinalText <- renderText({
    text
  })
}

4 个答案:

答案 0 :(得分:2)

您可以从会话对象中获取命名空间。在初始应用中更改http,如下所示:

myTextFunc

答案 1 :(得分:2)

你不应该从另一个输出$函数调用output $函数 - 它反对Shiny设计模式。

output$myFinalText <- renderUI({
    output$myText <- renderText({text})
    textOutput(ns('myText'))
})

如果你想知道,为什么这是非常糟糕的做法,请观看Joe Cheng关于&#39;有效反应式编程的教程&#39;来自这个网站:https://www.rstudio.com/resources/webinars/shiny-developer-conference/

您应该使用相当的reactiveValues或反应式表达式。你究竟应该使用什么取决于你想要达到的目标,所以没有详细的例子就很难说,但根据Joe Cheng的说法,一切都可以在没有嵌套输出或观察者的情况下完成。

答案 2 :(得分:1)

使用此renderUI等效项替换您的函数也有效:

myUI <- function(id) {
  ns <- NS(id)
  fluidRow(
    uiOutput(ns('myFinalText'))
  )
}

myTextFunc <- function(input, output, session, text) {
  output$myFinalText <- renderUI({
    text
  })
}

虽然这显然无法捕捉到你真正在做的事情的复杂性。在output$...中使用textOutputrenderUI就是这样的。我认为没有必要 - 您实际上不必使用textOutput函数在输出中包含文本。

编辑:我发现问题与名称空间和模块有关。执行output$myText <- renderText(text)后,结果将在tab1tab2的命名空间中结束。例如,尝试将textOutput更改为

textOutput('tab1-myText')

并观察会发生什么。我认为这就是为什么output$..中的renderUI变量存在问题。您可以通过callModule访问输入,这应该可以处理任何命名空间问题。

答案 3 :(得分:1)

很抱歉回答我自己的问题...但对于寻找类似解决方案的其他人来说,这可能会有所帮助。

以下是我在服务器端继承Shiny模块名称空间以动态呈现UI的需求。如果有更好的解决方法,请发表评论或发帖。

tab1NS <- NS('tab1')
tab2NS <- NS('tab2')

myUI <- function(ns) {
  tagList(
    fluidRow(
      radioButtons(ns('type'), 'Select Visual:',
                   choices = c('Table' = 'table',
                               'Plot' = 'plot'))
    ),
    fluidRow(
      uiOutput(ns('myCars'))
    )
  )
}

ui <- fluidPage(
  tabBox(id = 'myBox', width = 12,
         tabPanel('Tab1',
                  fluidRow(
                    myUI(tab1NS)
                  )),
         tabPanel('Tab2',
                  fluidRow(
                    myUI(tab2NS)
                  ))
         )
)

myTextFunc <- function(input, output, session, cars, ns) {
  getMyCars <- reactive({
    if (input$type == 'table') {
      output$table <- renderDataTable({datatable(cars)})
      dataTableOutput(ns('table'))
    } else{
      output$plot <- renderPlot({
        plot(cars$wt, cars$mpg)
      })
      plotOutput(ns('plot'))
    }
  })
  output$myCars <- renderUI({
    getMyCars()
  })
}

server <- function(input, output, session) {
  callModule(myTextFunc, 'tab1', session = session,
             mtcars[mtcars$am == 1, ], tab1NS)
  callModule(myTextFunc, 'tab2', session = session,
             mtcars[mtcars$am == 0, ], tab2NS)
}

shinyApp(ui = ui, server = server)