rstudio / shinydashboard

Shiny Dashboarding framework
https://rstudio.github.io/shinydashboard/
Other
892 stars 300 forks source link

Updating notificationMenuOutput - strange redirect to other tab #232

Closed shosaco closed 7 years ago

shosaco commented 7 years ago

I have a ShinyDashboard Page with a notificationMenu inside the header. I update these notifications from inside a Page in the Dashboard. This works perfectly, but after updating the notification Items, the User is redirected to the first Tab of the App - which is a strange behaviour. I expected to stay at the current page, even after the update was triggered. Does anyone have an explanation?

    library(shiny)
    library(shinydashboard)
    library(dplyr)

    ui <- dashboardPage(dashboardHeader(dropdownMenuOutput("notificationMenu")), 
                        dashboardSidebar(sidebarMenu(menuItem("Page 1", tabName = "page1"),
                                                     menuItem("Page 2", tabName = "page2"))),
                        dashboardBody(tabItems(
                          tabItem(tabName = "page1", h4("This is Page 1")),
                          tabItem(tabName = "page2", 
                                  textInput("text", "Enter News:", "New News."),
                                  actionButton("save", "Save")))))

    server <- function(input, output, session){
      raw_news <- reactiveValues()

      # Intial Header News: 1 Message from Admin
      raw_news$news <- data_frame(from = "Admin", text = "this is a message")

      # The notifications in header
      output$notificationMenu <- renderMenu({
        raw_news <- raw_news$news

        dropdownMenu(
          messageItem(raw_news$from[1], raw_news$text[1])
        )
      })

      # save a new notification
      observeEvent(input$save, {
        raw_news$news <- data.frame(from = "User", text = input$text)
      }) 
    }

    shinyApp(ui = ui, server = server)

enter image description here

bborgesr commented 7 years ago

Hmm, that does seem strange. However, I think there's a simple solution here:

  1. add the argument id = "tabs" to the sidebarMenu() call in the UI;
  2. add a line of code (updateTabItems(session, "tabs", "page2")) at the end of your observeEvent().

Here's your app with these two changes:

app.R ```r library(shiny) library(shinydashboard) library(dplyr) ui <- dashboardPage(dashboardHeader(dropdownMenuOutput("notificationMenu")), dashboardSidebar(sidebarMenu(id = "tabs", menuItem("Page 1", tabName = "page1"), menuItem("Page 2", tabName = "page2"))), dashboardBody(tabItems( tabItem(tabName = "page1", h4("This is Page 1")), tabItem(tabName = "page2", textInput("text", "Enter News:", "New News."), actionButton("save", "Save"))))) server <- function(input, output, session){ raw_news <- reactiveValues() # Intial Header News: 1 Message from Admin raw_news$news <- data_frame(from = "Admin", text = "this is a message") # The notifications in header output$notificationMenu <- renderMenu({ raw_news <- raw_news$news dropdownMenu( messageItem(raw_news$from[1], raw_news$text[1]) ) }) # save a new notification observeEvent(input$save, { raw_news$news <- data.frame(from = "User", text = input$text) updateTabItems(session, "tabs", "page2") }) } shinyApp(ui = ui, server = server) ```


In an unrelated matter, one thing that took me a while to understand in your app was that you wanted to replace the same message in your dropdownMenu over and over again (instead of adding more messages). If you actually want to add messages, instead of replacing them, your code needs to change a bit.

In case you're interested:

app.R (modified to add messages instead of replacing the same one) ```r library(shiny) library(shinydashboard) ui <- dashboardPage( dashboardHeader( dropdownMenuOutput("notificationMenu") ), dashboardSidebar( sidebarMenu(id = "tabs", menuItem("Page 1", tabName = "page1"), menuItem("Page 2", tabName = "page2") ) ), dashboardBody( tabItems( tabItem(tabName = "page1", h4("This is Page 1")), tabItem(tabName = "page2", textInput("text", "Enter News:", "New News."), actionButton("save", "Save") ) ) ) ) server <- function(input, output, session){ news <- reactiveValues( init = list(from = "Admin", message = "This is a message") ) output$notificationMenu <- renderMenu({ items <- lapply(reactiveValuesToList(news), function(el) { messageItem(from = el$from, message = el$message) }) dropdownMenu(type = "messages", badgeStatus = "info", .list = items) }) observeEvent(input$save, { # save a new message news[[paste0("id", input$save)]] <- list( from = "User", message = input$text ) updateTabItems(session, "tabs", "page2") }) } shinyApp(ui = ui, server = server) ```


I think this closes this issue. If you have more questions, let me know and I can re-open.

shosaco commented 7 years ago

Thank you. Of course I am adding messages, but for the sake of argument I simply replaced the message in the menu, since adding didn't add to demonstrating the problem.

However, I noticed this bug is the same as #229 and your proposed solution works in the special case that I have only 1 Tab from where I update the news. If there is Page2 and Page3 and both have a "Save"-Button which updates the header-Menu, the workaround doesn't work any more.

I will observe #229 to solve my problem, thanks!

bborgesr commented 7 years ago

Actually, my proposed solution could work if you don't hardcode the value, and instead make it whatever is currently selected: updateTabItems(session, "tabs", input$tabs) (this still works as expected and it's more general).

This is the best answer I can give you (and the others) right now. It is a bit surprising this is happening, but I'm not currently working on this project right now, so I'd recommend using this workaround until I can understand the root of this issue.

shosaco commented 7 years ago

Thanks a lot!