rshinyshinydashboard

Update Text of a shinydashboard::menuItem


I'm trying to implement a reactive text for a shinydashboard menuItem without having to use renderMenu in the server. The reason is that every time the menu is rendered, it resets all items in the menu to default. However, some of them are also reactive, e.g. an actionbutton being disabled upon an event.

I suspect this might be possible with runjs, but I don't know how to properly address just the text of a menu item of a specific id. I wasn't able to use isolate for the things I didn't want to be reactive in renderMenu; I was getting errors when I tried that.

This below example is not desired, as each time the menu is rendered, it resets everything, regardless of how the items had subsequently been changed. In this example, the button and checkbox are reset to an enabled state, despite disabling them upon button click. In contrast and to illustrate what I mean, the button and checkbox in menu 1 remain disabled.

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

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    sidebarMenu(
    menuItem(
      "Menu1",
      actionButton("dummy1", "Dummy Button 1"),
      checkboxInput('dummy3', 'Dummy 3')
      ),
    menuItemOutput('menu2')
    )
  ),
  dashboardBody(
    shinyjs::useShinyjs(),
    textInput("name", label='New Menu Label', value = ""),
    actionButton("update", "Update Label")
    )
)
  
server <- function(input, output, session){
  
  menulabel<-reactiveVal('Menu2')
  
  output$menu2<-renderMenu({
    menuItem(
      menulabel(),
      actionButton('dummy2', 'Dummy Button 2'),
      checkboxInput('dummy4', 'Dummy 4')
    )
  })
  
  observeEvent(input$update,{
    menulabel(input$name) #instead of a reactive label and renderMenu(), use runjs() here?
    shinyjs::disable('dummy1')
    shinyjs::disable('dummy2')
    shinyjs::disable('dummy3')
    shinyjs::disable('dummy4')
  })
}

shinyApp(ui, server)

Solution

  • What you can do is to take the first span of your menu2 and update its html(). Therefore you can replace the menulabel(input$name) with

    runjs(paste0("$('#menu2 span').first().html('", input$name, "')"))
    

    enter image description here