Search code examples
rshinyreactive-programmingshinydashboard

How to trigger action on clicking in menuItem?


I want to trigger some action on clicking the menuItem. I use observe here: when I click 'Drivers' item I want some text to be returned in the console. Unfortunately, when I run the app the error comes up: Error in if: argument is of length 0. My menuItem exists, id is also ok so don't know why this error shows up. Here is reproducible code (observe is on the bottom of my code):

library(shiny)
library(bs4Dash)
library(leaflet)


bodyTag <- dashboardBody(
  tags$head(
    tags$style(
      "#map {
          height: calc(100vh - 57px) !important;
        }"
    )
  ),
  
  tabItems(
    tabItem(
      tabName = "live",
      box(
        title = "LIVE",
        id = "panel",
        height = 450,
        collapsible = TRUE
      )
    ),
    
    tabItem(
      tabName = "drivers",
      box(
        title = "Drivers",
        id = "panel",
        height = 450,
        collapsible = TRUE
      )
    ),
    tabItem(
      tabName = "customers",
      box(
        title = "Customers",
        id = "panel",
        height = 450,
        collapsible = TRUE
      )
    )    
  ),

  leafletOutput("map")
)



ui <- dashboardPage(
  dark = TRUE,
  
  header = dashboardHeader(
    title = h5("DEMO app")
  ),
  
  
  sidebar = dashboardSidebar(
    fixed = TRUE,
    collapsed = TRUE,
    expandOnHover = FALSE,
    status = "purple",
    
    customArea = fluidRow(
      actionButton(
        inputId = "myAppButton",
        label = NULL,
        icon = icon("users"),
        width = NULL,
        status = "primary",
        style = "margin: auto",
        dashboardBadge(1, color = "danger")
      )
    ),
    
    sidebarMenu(
      id = "sidebarID",
      menuItem("Live", tabName = "live", icon = icon("circle")),
      menuItem("Drivers", tabName = "drivers", icon = icon("user-friends")),
      menuItem("Customers", tabName = "customers", icon = icon("building"))
    )
  ),
  body = bodyTag
)



server <- function(input, output) {
  observeEvent(input$sidebarID, {
    updateBox("panel", action = "toggle")
  })
  

  output$map <- renderLeaflet({
    leaflet() %>%
      setView(lng = -73.98928, lat = 40.75042, zoom = 6) %>%
      addProviderTiles("CartoDB.Positron")
  })
  
   
  # the problem is here
  observe({
    
    if(input$tabs == "drivers") {
      print("Drivers")
      #print(input$tabs)
    } else {
      print("other tabs")
    }
  })

}

shinyApp(ui = ui, server = server)

I'm pretty sure that input$tabs is how I should get to the given menuItem but maybe I'm wrong.


Solution

  • You're wrong. Many other posted solutions to this problem use tabs as the id of the sidebar menu, but you don't:

        sidebarMenu(
          id = "sidebarID",
          menuItem("Live", tabName = "live", icon = icon("circle")),
          menuItem("Drivers", tabName = "drivers", icon = icon("user-friends")),
          menuItem("Customers", tabName = "customers", icon = icon("building"))
        )
    
    

    So you need

      observe({
        if(input$sidebarID == "drivers") {
          print("Drivers")
          #print(input$tabs)
        } else {
          print("other tabs")
        }
      })
    

    It's a simple typo.