我在尝试用模块把应用分成多个页面,但现在无法再从子模块访问输入了
为了重现我当前应用中的错误,我做了一个简单的玩具示例来解释我想解决的问题。
我想要将我的 app1.R 里的页面变成模块(以便更好地组织,正如 https://mastering-shiny.org/scaling-packaging.html 中所建议的那样)。
app1.R
library(shiny)
ui <- navbarPage(
"My Fancy App",
tabPanel("page1",
fluidPage(
mainPanel(
titlePanel("Page-1"),
dataUI("data1"),
verbatimTextOutput("choice1")
)
)
),
tabPanel("page2",
fluidPage(
mainPanel(
titlePanel("Page-2"),
dataUI("data2"),
verbatimTextOutput("choice2")
)
)
)
)
server <- function(input, output, session) {
data1 <- dataServer("data1")
output$choice1 <- renderText({paste0("Your choice is: ", data1())})
data2 <- dataServer("data2")
output$choice2 <- renderText({paste0("Your choice is: ", data2())})
}
shinyApp(ui, server)
R\data.R
dataUI <- function(id) {
selectInput(NS(id, "dataset"), "Pick a letter", choices = LETTERS)
}
dataServer <- function(id) {
moduleServer(id, function(input, output, session) {
out <- reactive(input$dataset)
})
}
我的尝试是创建两个模块(page1.R 和 page2.R),并在我新的 app2.R 中使用它们,但我现在看不到页面底部的文本输出。在调试时我发现 input$dataset 不再像分割前那样被读取。现在,data.R 已经成了新 page*.R 模块的某种“子模块”。
现在我怎么访问它的值?由于我的实际应用相当复杂,我想知道是否有一个巧妙的方法来实现这一点(例如通过将父会话的输入等传递给子模块,或类似的方式)。
app2.R
library(shiny)
ui <- navbarPage(
"My Fancy App",
tabPanel("page1", page1UI("tab1")),
tabPanel("page2", page2UI("tab2")),
)
server <- function(input, output, session) {
page1Server("tab1")
page2Server("tab2")
}
shinyApp(ui, server)
R\page1.R
page1UI <- function(id) {
fluidPage(
mainPanel(
titlePanel("Page-1"),
dataUI("data1"),
verbatimTextOutput("choice1")
)
)
}
page1Server <- function(id) {
moduleServer(id, function(input, output, session) {
data <- dataServer("data1")
output$choice1 <- renderText({paste0("Your choice is: ", data())})
})
}
R\page2.R
page2UI <- function(id) {
fluidPage(
mainPanel(
titlePanel("Page-2"),
dataUI("data2"),
textOutput("choice2")
)
)
}
page2Server <- function(id) {
moduleServer(id, function(input, output, session) {
data <- dataServer("data2")
output$choice2 <- renderText({paste0("Your choice is: ", data())})
})
}
解决方案
我想我找到了答案:我需要在模块中的输入前加上命名空间,例如 dataUI(NS(id,"data1"))。
下面是更正后的代码:
R\data.R
dataUI <- function(id) {
selectInput(NS(id,"dataset"), "Pick a letter", choices = LETTERS)
}
dataServer <- function(id) {
moduleServer(id, function(input, output, session) {
return(reactive(input$dataset))
})
}
R\page1.R
page1UI <- function(id) {
fluidPage(
mainPanel(
titlePanel("Page-1"),
dataUI(NS(id,"data1")),
verbatimTextOutput(NS(id,"choice1"))
)
)
}
page1Server <- function(id) {
moduleServer(id, function(input, output, session) {
data <- dataServer("data1")
output$choice1 <- renderText({paste0("Your choice is: ", data())})
})
}
R\page2.R
page2UI <- function(id) {
fluidPage(
mainPanel(
titlePanel("Page-2"),
dataUI(NS(id,"data2")),
textOutput(NS(id,"choice2"))
)
)
}
page2Server <- function(id) {
moduleServer(id, function(input, output, session) {
data <- dataServer("data2")
output$choice2 <- renderText({paste0("Your choice is: ", data())})
})
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。