我正在使用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
})
}
答案 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$...
中使用textOutput
和renderUI
就是这样的。我认为没有必要 - 您实际上不必使用textOutput
函数在输出中包含文本。
output$myText <- renderText(text)
后,结果将在tab1
或tab2
的命名空间中结束。例如,尝试将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)