在“nav_menu”/“nav_panel”中重复使用模块

Re-using a Module in `nav_menu`/ `nav_panel`

提问人:Karsten W. 提问时间:11/16/2023 最后编辑:Karsten W. 更新时间:11/17/2023 访问量:32

问:

在我闪亮的应用程序中,我想允许用户选择一个主题,然后显示有关该主题的一些信息。

每个主题的信息看起来都相似,并在一个闪亮的模块中定义。用户可以使用 选择主题。subj_ui() / subj_srv()nav_menu/nav_panel

当前的方法为每个主题“实例化”一个模块,如下所示:

subj_ui <- function(id) {
    ns <- shiny::NS(id)
    bslib::page(
        bslib::value_box(
            title = "Position",
            value = shiny::textOutput(ns("pos")),
            max_height = "200px",
            width="25%"
        )
    )
}
subj_srv <- function(id) shiny::moduleServer(id, function(input, output, session) {
    output$pos <- shiny::renderText(which(LETTERS==id))
})

ui <- bslib::page_navbar(
    id="nav",
    title="Static Menu",
    selected="A",
    bslib::nav_menu("Subject", 
        bslib::nav_panel(title="A", value="A", subj_ui("A")),
        bslib::nav_panel(title="B", value="B", subj_ui("B")),
        bslib::nav_panel(title="C", value="C", subj_ui("C"))
    )
)

server <- function(input, output, session) {
    subj_srv("A")
    subj_srv("B")
    subj_srv("C")
}

shiny::shinyApp(ui, server)

这将为每个主题创建一个服务器模块。但是,在我的应用程序中,主题数量更多(大约 20 个),ui 和服务器功能更复杂(涉及数据库查询)。

所以我想知道我是否可以只“实例化”一个模块并将其重用于所有主题?

(使用 时,我可以定义包含主题信息(如“subj_A”)的菜单项,观察并设置对主题的反应并手动调用。bslib 有类似的路线吗?shinydashboardinput$tabsupdateTabItems

r 闪亮的 bslib

评论

0赞 Karsten W. 11/16/2023
相关新闻: stackoverflow.com/q/76408603/216064

答:

0赞 Karsten W. 11/17/2023 #1

终于想出了一个解决方案。不是很优雅,仍然对最佳实践感兴趣。

请注意,该对象不在 .如果是这样,当用户选择菜单项时,菜单将保持打开状态。请参阅此处进行讨论。nav_panel_hiddennav_menu

subj_ui <- function(id) {
    ns <- shiny::NS(id)
    bslib::page(
        bslib::value_box(
            title = "Position in the Alphabet",
            value = shiny::textOutput(ns("pos")),
            max_height = "200px",
            width="25%"
        )
    )
}
subj_srv <- function(id, subj) shiny::moduleServer(id, function(input, output, session) {
    # message("subj=", subj())
    output$pos <- shiny::renderText({
        shiny::req(shiny::isTruthy(subj$val))
        which(LETTERS==subj$val)
    })
})

ui <- bslib::page_navbar(
    id="nav",
    title="Dynamic Menu",
    selected="subj",
    bslib::nav_panel(value="start", title="Start", shiny::p("Some introductory notes.")),
    bslib::nav_menu("Subject", 
        bslib::nav_panel(value="subj_A", title="A"),
        bslib::nav_panel(value="subj_B", title="B"),
        bslib::nav_panel(value="subj_C", title="C")
    ),
    bslib::nav_panel_hidden(value="subj", subj_ui("subj"))
)

server <- function(input, output, session) {
    curr_subject <- shiny::reactiveValues()
        
    shiny::observeEvent(input$nav, {
        if(grepl("^subj_", input$nav)) {
            curr_subject$val <- gsub("^subj_", "", input$nav)
            bslib::nav_select("nav", "subj")
        }
    })
    
    subj_srv("subj", subj=curr_subject)
    
}

shiny::shinyApp(ui, server)