1

I have this code:

library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = dashboardPage(
    header = dashboardHeader(userOutput("user")),
    sidebar = dashboardSidebar(shinyjs::useShinyjs(),uiOutput("sidebarpanel")),
    body = dashboardBody(uiOutput("body")),
    title = "DashboardPage"
  ),
  server = function(input, output) {
    output$user <- renderUser({
      dashboardUser(
        name = "Divad Nojnarg", 
        image = "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg", 
        title = "shinydashboardPlus",
        subtitle = "Author", 
        footer = p("The footer", class = "text-center"),
        fluidRow(
          actionButton("personalInfo","Personal Info")
        )
      )
    })
    
    observeEvent(input$personalInfo, {
      output$body <- renderUI({h4("Personal Info Dahsboard (no menuItem)")})
    })
    
    output$sidebarpanel <- renderUI({
        sidebarMenu(id="tabs",
                        menuItem("Dashboard 1", tabName = "dashboard1", icon = icon("dashboard"))        
                        ,menuItem("Dashboard 2", tabName = "dashboard2", icon = icon("dashboard"))
        )
    }) 
    
    output$body <- renderUI({
      
      tabItems(
        tabItem(tabName ="dashboard1",
                fluidRow(box(width = 12, h4("Dashboard 1 (menuItem)"))))
        ,tabItem(tabName ="dashboard2",
                 fluidRow(box(width = 12, h4("Dashboard 2 (menuItem)"))))
      )
    })
  }
)

I would like to do two things:

First: When I click on "Personal Info" button, then, prevent the menuItem to be shadowed (I assume I need to remove the class "selected" or "active" or something like that)

enter image description here

Second: I want to fix this: After pressing "Personal Info" button, the menuItems do not work:

enter image description here

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
Lev
  • 693
  • 1
  • 8
  • 24

1 Answers1

2

As already shown in my earlier answer here we can use a hidden menuItem to modify the body content independent from the visibly selected menuItem.

Furthermore, I'd recommend to stop using renderUI in this scenario. In general it is slower to re-render a UI element instead of updating an existing element (here we can switch to the hidden menuItem via updateTabItems - however, this applies also to e.g. using updateSelectInput instead of renderUI({selectInput(...)})). In this context you should also question whether you really need the to create the dashboardUser on the server side.

If you really need a server side generated dashboardSidebar you still should not use renderUI - There are the renderMenu() / sidebarMenuOutput() functions available for this. Please see the related docs here.

library(shiny)
library(shinyjs)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = dashboardPage(
    header = dashboardHeader(userOutput("user")),
    sidebar = dashboardSidebar(shinyjs::useShinyjs(),
                               sidebarMenu(id="tabs",
                                           menuItem("Tab 1", tabName = "tab1", icon = icon("dashboard")),
                                           menuItem("Tab 2", tabName = "tab2", icon = icon("dashboard")),
                                           hidden(menuItem("Personal Tab", tabName = "personal_tab", icon = icon("dashboard")))
                               )),
    body = dashboardBody(useShinyjs(),
                         tabItems(
                           tabItem(tabName ="tab1",
                                   fluidRow(box(width = 12, h4("Tab 1 (menuItem)")))),
                           tabItem(tabName ="tab2",
                                   fluidRow(box(width = 12, h4("Tab 2 (menuItem)")))),
                           tabItem(tabName ="personal_tab",
                                          fluidRow(box(width = 12, h4("Personal Info Dahsboard (no menuItem)"))))
                         )
    ),
    title = "DashboardPage"
  ),
  server = function(input, output, session) {
    output$user <- renderUser({
      dashboardUser(
        name = "Divad Nojnarg", 
        image = "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg", 
        title = "shinydashboardPlus",
        subtitle = "Author", 
        footer = p("The footer", class = "text-center"),
        fluidRow(
          actionButton("personalInfo","Personal Info")
        )
      )
    })
    
    observeEvent(input$personalInfo, {
      shinydashboard::updateTabItems(session, inputId = "tabs", selected = "personal_tab")
    })
  }
)
ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • Definitely I was not doing in the proper way. Thank you very much. It works!. My dashboardUser is taking data from a users table. Thats why I think I should use `sidebarMenuOutput` (I tried with `uiOutput` and it also works, which is better?). And my last question: in my real app I have `body <- dashboardBody(shinyjs::useShinyjs(), uiOutput("body"))`. and `output$body <- renderUI({ tabItems( tabItem(...)) })` I was looking something like "renderTab", but seems it does not exists. Is there any best way to render the body?. Thanks! – Lev Dec 19 '22 at 13:55
  • 2
    In general you should avoid `renderUI` where ever you can and use update* functions instead. If there are render functions available along with specifc output functions (same library) use them and don't mix them with `renderUI`. The [body](https://rstudio.github.io/shinydashboard/structure.html#body) may *contain any regular shiny content* - this includes `renderUI` calls if needed. – ismirsehregal Dec 19 '22 at 14:13