Home > Back-end >  Where to put Shiny subModule server in {brochure} page?
Where to put Shiny subModule server in {brochure} page?

Time:02-23

Background I am using {brochure} and {golem} to build a shiny app. I have one outer module dashboard that consists of inner modules subGrid2 which display different graphs based on the sideBar tab.

The goal is to have a few modules with server fragments written in external module that can be used for generating data for a certain tab. In the REPREX below I have a fake graph generated from {shinipsum} to be displayed on the "Home" tab, this plot is generated in a {golem} module. You can see where I reference the inner module mod_subGrid2_ui/server in the mod_dashboard_server.

Problem

This module nesting logic should result in a graph showing in the body of the "home" tab, however, I am met with an empty page. I can see the container.plot when I use Right Click > Inspect Element, but don't know where the bug/my logic goes awry causing the plot no to be shown?

-using the reprex below replicates my issue-

TL/DR

Where do I put the module server function in a shiny app on {brochure} framework in order to correctly render server plots/data...?

REPREX

#22.2.22
library(brochure)

library(shiny)

library(shinipsum)

library(shinydashboard)

library(shinydashboardPlus)

# DASHBOARD ----
mod_dashboard_ui <- function(id) {
    ns <- NS(id)
    # define dashboardPage parts =====

    header <- shinydashboardPlus::dashboardHeader(
        title = "test"
    )

    sidebar <- shinydashboardPlus::dashboardSidebar(
        shinydashboard::sidebarMenu(
            # Setting id makes input$tabs give the tabName of currently-selected tab
            id = "dashTabs",
            menuItem("Home", tabName = "home", icon = icon("tachometer-alt")),
            menuItem("Portfolio", tabName = "portfolio", icon = icon("chart-line"), badgeLabel = "new",
                     badgeColor = "green")
        )
    )


body <- shinydashboard::dashboardBody(
    # Enable shinyjs
    shinyjs::useShinyjs(),

    shinydashboard::tabItems(
        shinydashboard::tabItem("home",
                                shiny::tagList(
                                    div(p("Content for dashboard goes here -- GRID MODULE")),
                                    mod_subGrid2_ui("subGrid2_ui_1")
                                )
        ),
        shinydashboard::tabItem("portfolio",
                                shiny::tagList(
                                    div(p("Content for dashboard goes here -- PORTFOLIO MODULE")),
,
                                        titlePanel(title = "A different module goes here")
                                )
        )
    )
)

    # Create Dashboard Page - combine parts =====
    shinydashboardPlus::dashboardPage(
        skin = "midnight",
        header = header,
        sidebar = sidebar,
        body = body
    )
}


# **DASHBOARD MODULE SERVER**


mod_dashboard_server <- function(id) {
    moduleServer(id, function(input, output, session) {
        ns <- session$ns

        mod_subGrid2_server("subGrid2_ui_1")

        # I also tried this, uncomment to try
        # observeEvent(input$dashTabs,{
        #   if(input$dashTabs == "home"){
        #     # <subGrid> server fragment
        #     mod_subGrid2_ui("subGrid2_ui_1")
        #   }
        # }, ignoreNULL = TRUE, ignoreInit = TRUE)

    })
}


dashboard <- function(id = "dashboard", href = "/") {
    page(
        # HTTP Endpoint '/'
        href = href,
        ui = mod_dashboard_ui(id = id),
        server = function(input, output, session) {
            mod_dashboard_server(id = id)
        }
    )
}
# Dash end ----

mod_subGrid2_ui <- function(id){
    ns <- NS(id)
    tagList(
        fluidPage(

            # Application title
            titlePanel("PLOT GOES UNDER HERE", windowTitle = "Test App"),

            # Show a plot of the generated distribution
            mainPanel(
                plotOutput(ns("plot"))
            )
        )
    )
}


mod_subGrid2_server <- function(id){
    moduleServer( id, function(input, output, session){
        ns <- session$ns

        output$plot <- renderPlot({
            shinipsum::random_ggplot(type = "line")
        })
    })
}

## To be copied in the UI
# mod_subGrid2_ui("subGrid2_ui_1")

## To be copied in the server
# mod_subGrid2_server("subGrid2_ui_1")

# innerModule end ----

brochure::brochureApp(
    dashboard(),
    onStart = NULL,
    options = list(),
    wrapped = shiny::tagList
)
# Created on 2022-02-22 by the reprex package (v2.0.0)

This graph should be on home tab

CodePudding user response:

When using a module nested inside another module, you need to ns() the id of the nested UI function. So here, mod_subGrid2_ui(ns("subGrid2_ui_1")).

Here is a minimal reprex:

mod_subGrid2_ui <- function(id) {
  ns <- NS(id)
  tagList(
    plotOutput(ns("plot"))
  )
}

mod_subGrid2_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    output$plot <- renderPlot({
      shinipsum::random_ggplot()
    })
  })
}

mod_Grid_ui <- function(id) {
  ns <- NS(id)
  tagList(
    mod_subGrid2_ui(ns("subGrid2_ui_1"))
  )
}

mod_Grid_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    mod_subGrid2_server("subGrid2_ui_1")
  })
}

brochureApp(
  page(
    href = "/",
    ui = tagList(
      mod_Grid_ui("grid_1")
    ),
    server = function(input, output, session) {
      mod_Grid_server("grid_1")
    }
  )
)
  • Related