Search code examples
rshinymoduleshinydashboard

Multiple tabItems in one shiny module


Hello im relatively new to R Programming and Shiny. I´m currently developing an shiny dashboard application. I´m stuck a the moment with the problem of how to have multiple tabItems in one module. In the real app I need to pass a lot more information's between the modules and the submenu's aren't alike. So is there a way to make this work? Thanks so much for your help!

library(shiny)
library(shinydashboard)
library(shinydasboardPlus)

#submodules
submodule_ui <- function(id,tabName){
  ns <- NS(id)
  
  tabItem(
    tabName = tabName,
    boxPlus(
      title = "some title",
      textOutput(ns("some_output"))
    )
  )
  
}

submodule_server <- function(id,see){
  moduleServer(
    id,
    function(input, output, session){
      output$some_output <- renderText({
        see
      })
    }
  )
}


#module
module_ui <- function(id,tabName1,tabName2){
  ns <- NS(id)
  
  submodule_ui(ns("sub1"),
               tabName = tabName1)
  submodule_ui(ns("sub2"),
               tabName = tabName2)
  
}

module_server <- function(id){
  moduleServer(
    id,
    function(input, output, session){
      submodule_server("sub1","hello")
      submodule_server("sub2","world !")
    }
  )
}


#app

ui <- dashboardPagePlus(
  header = dashboardHeaderPlus(
    title = "dummy app"
  ),
  sidebar = dashboardSidebar(
    sidebarMenu(
      menuItem(
        text = "home",
        tabName = "home"
      ),
      menuItem(
        text = "submodule1",
        tabName = "subtab1"
      ),
      menuItem(
        text = "submodule2",
        tabName = "subtab2"
      ),
      menuItem(
        text = "some other tabItems",
        tabName = "some_other_tabItems"
      )
    )
  ),
  body = dashboardBody(
    tabItems(
      tabItem(
        tabName = "home",
        box(
          title = "home of the app",
          width = "auto"
        )
      ),
      module_ui(
        id = "module",
        tabName1 = "subtab1",
        tabName2 = "subtab2"
      ),
      tabItem(
        tabName = "some_other_tabItems",
        box(
          title = "some other content"
        )
      )
    )
  )
)

server <- function(input, output){
  module_server("module")
}

shinyApp(ui,server)

´´´

Solution

  • It appears there was some issues with getting the tab item wrapper around the submodules - it was only producing the second submodule. Modules act like functions as they tend to produce the final call. You can wrap things in a list or taglist to return more items. In the meantime...

    By moving the tabItems wrapper into the module, it was able to create the list properly and produce both tabs.

    Note: I converted the functions to shinydashboard as I could figure out where the xxxPlus functions came from.

    library(shiny)
    library(shinydashboard)
    #submodules
    submodule_ui <- function(id,tabName){
      ns <- NS(id)
      
      tabItem(
        tabName = tabName,
        box(
          title = "some title",
          textOutput(ns("some_output"))
        )
      )
      
    }
    
    submodule_server <- function(id,see){
      moduleServer(
        id,
        function(input, output, session){
          output$some_output <- renderText({
            see
          })
        }
      )
    }
    
    
    #module
    module_ui <- function(id,tabName1,tabName2){
      ns <- NS(id)
      ### tabsItems now produced in module, submodules separated by comma
      tabItems(
        submodule_ui(ns("sub1"),
                     tabName = tabName1),
        submodule_ui(ns("sub2"),
                     tabName = tabName2)
      )
      
      
    }
    
    module_server <- function(id){
      moduleServer(
        id,
        function(input, output, session){
          submodule_server("sub1","hello")
          submodule_server("sub2","world !")
        }
      )
    }
    
    
    #app
    
    ui <- dashboardPage(
      header = dashboardHeader(
        title = "dummy app"
      ),
      sidebar = dashboardSidebar(
        sidebarMenu(
          menuItem(
            text = "submodule1",
            tabName = "subtab1"
          ),
          menuItem(
            text = "submodule2",
            tabName = "subtab2"
          )
        )
      ),
      body = dashboardBody(
      
          module_ui(
            id = "module",
            tabName1 = "subtab1",
            tabName2 = "subtab2"
          
        )
      )
    )
    
    server <- function(input, output){
      module_server("module")
    }
    
    shinyApp(ui,server)