Shiny dashboard - hide menuitem in server generated sidebar UI - r

I have a server generated sidebar. After its creation, I want to hide its first element. The observer doing the hiding is executed, however, the menuitem is not hidden. I am trying to figure out, why it does not work. Any thoughts?
PS. The CSS selector appears to be correct, as all works when the UI is not created on the server.
library(shiny)
library(shinyjs)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
uiOutput("sidebar_ui")
),
dashboardBody(
shinyjs::useShinyjs()
)
)
server <- function(session, input, output)
{
rv <- reactiveValues()
output$sidebar_ui <- renderUI({
rv$trigger_sidebar_config <- 0
cat("\nSidebar create")
sidebarMenu(id = "sidebar",
menuItem("Menu1", tabName = "tab_menu_1"), # to be hidden
menuItem("Menu2", tabName = "tab_menu_2") )
})
observeEvent(rv$trigger_sidebar_config, {
cat("\nSidebar config")
shinyjs::hide(selector = '[data-value="tab_menu_1"]') # hide menuitem
})
}
shinyApp(ui, server)

Your observeEvent is executed too early because the reactive value trigger_sidebar_config is updated during the same cycle as renderUI. Accordingly shiny tries to hide an UI element which isn't existing yet (you would have to wait for the UI beeing rendered, instead of it's calculation beeing triggered, for this to work).
You can test this e.g. via delaying the execution of shinyjs::hide - it works when triggered by an actionButton (Please see my below example) or you have a look at the reactlog:
Here you can see, that the observeEvent triggered via trigger_sidebar_config finished calculating after 3ms but the sidebar wasn't ready at this time (30ms).
If you want the tab to be hidden on startup you can use hidden() in your renderUI call (see Menu3):
library(shiny)
library(shinyjs)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
uiOutput("sidebar_ui")
),
dashboardBody(
shinyjs::useShinyjs(),
actionButton("hide", "hide tab")
)
)
server <- function(session, input, output)
{
rv <- reactiveValues()
output$sidebar_ui <- renderUI({
rv$trigger_sidebar_config <- 0
cat("\nSidebar create")
sidebarMenu(id = "sidebar",
menuItem("Menu1", tabName = "tab_menu_1"), # to be hidden
menuItem("Menu2", tabName = "tab_menu_2"),
shinyjs::hidden(menuItem("Menu3", tabName = "tab_menu_3")))
})
observeEvent(input$hide, {
cat("\nSidebar config")
shinyjs::hide(selector = '[data-value="tab_menu_1"]') # hide menuitem
})
}
shinyApp(ui, server)
In this context please also see ?renderMenu().

Related

Toggle display of sidebar menu in shinydashboard programmatically

I am working with R shiny dashboard and was wondering if I can collapse/show the sidebar with an additional button, just like the already existing one on top of the sidebar.
Is that possible?
Cheers
You can add / remove the needed css class to / from the body via shinyjs:
library(shiny)
library(shinyjs)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
shinyjs::useShinyjs(),
actionButton("toggle_btn", "Toggle sidebar")
)
)
server <- function(input, output, session) {
observeEvent(input$toggle_btn, {
shinyjs::toggleClass(selector = "body", class = "sidebar-collapse")
})
}
shinyApp(ui, server)

Using the "click" function to programatically launch R shiny Action Button

I recently came across the click() function and want to incorporate this in to my app.
https://www.rdocumentation.org/packages/shinyjs/versions/1.1/topics/click
However attempting to run the given example:
if (interactive()) {
library(shiny)
library(shinyjs)
shinyApp(
ui = fluidPage(
useShinyjs(), # Set up shinyjs
"Count:", textOutput("number", inline = TRUE), br(),
actionButton("btn", "Click me"), br(),
"The button will be pressed automatically every 3 seconds"
),
server = function(input, output) {
output$number <- renderText({
input$btn
})
observe({
click("btn")
invalidateLater(3000)
})
}
)
}
# }
Did not give the desired behaviour. It appears no auto-clicking is taking place! Can anybody explain? Thanks in advance.

Shinydashboard bookmarking does not bookmark the active tab if the tab is rendered from the server side

When a bookmarked shinydashboard with multiple tabs is loaded, the previously active tab should be active again on load - i.e., if the dashboard has 2 tabs and the bookmark button is on tab 2, tab 2 should be active when the bookmark is loaded. This works correctly if both tabs were created in the ui.
However, if tab 2 was created on the server side via renderMenu, when the bookmark is loaded tab 1 is active instead of tab 2.
The example below shows this behavior. If you move the bookmark to tab 3, it will work correctly.
library(shiny)
library(shinydashboard)
enableBookmarking(store = "server")
ui <- function(request){
dashboardPage(
dashboardHeader(title = "demo"),
dashboardSidebar(
sidebarMenu(id="sidebar",
menuItem("Static 1", tabName = "static1"),
sidebarMenuOutput("menu"),
menuItem("Static 2", tabName = "static2")
)
),
dashboardBody(
tabItems(
tabItem(tabName="static1", h2("something1")),
tabItem(tabName="dynamic", h2("something2"), bookmarkButton()),
tabItem(tabName="static2", h2("something3"))
)
)
)
}
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(
menuItem("Dynamic", tabName="dynamic")
)
})
}
shinyApp(ui = ui, server = server)
I expect that a bookmark should load the active tab regardless of whether the tab was created in the ui or rendered by the server.
Edit - I tried passing the sidebarMenu id to the server as well, but that didn't work:
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(id="sidebar",
menuItem("Dynamic", tabName="dynamic")
)
})
}

sidebarMenu with subItems is non-responsive in dashboardbody shiny

I have the below code and upon clicking the "Dataset" in sidebar menu with sub-items, the dashboardbody does not change to the text in the tabItem. Ideally, when "Dataset" is clicked the body should display "Dataset menu sub-items content". I referred similar threads but no success. Could anyone help.
library(shiny)
library(shinydashboard)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Documentation", tabName = "documentation"),
menuItem("Dataset", tabName="dataset",icon = icon("info"),
menuSubItem(fileInput("Input", "Upload input file:")),
menuSubItem(numericInput("samples",label="Samples",value=0,max=10)))))
body <- dashboardBody(
tabItems(
tabItem(tabName = "documentation",div(p("Dashboard tab content"))),
tabItem(tabName = "dataset",div(p("Dataset menu sub-items content")))))
ui <- dashboardPage(dashboardHeader(title = "Test"),
sidebar,
body)
server <- function(input, output, session) {
}
shinyApp(ui, server)

Dynamic selectizeInput in shiny

I am trying to allow the user to type the value in the selectizeInput to find what they are searching from a long list (thus avoiding the scrolling action). When the user deletes the default value "None" (in this example), they are kicked out of the input box where they have to go back and type what they are seeking. Is there a way to avoid this so the user can backspace "None" to delete it and search for a value without being pushed out of the box?
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic selectInput"),
dashboardSidebar(
sidebarMenu(
menuItemOutput("menuitem")
)
),
dashboardBody(
selectizeInput("heir1","Heirarchy1",c("NONE",letters),selected="NONE"),
selectizeInput("heir2","Heirarchy2",c("NONE",letters),selected="NONE"),
selectizeInput("heir3","Heirarchy3",c("NONE",letters),selected="NONE")
)
)
server <- function(input, output, session) {
output$menuitem <- renderMenu({
menuItem("Menu item", icon = icon("calendar"))
})
heirarchy<-c(letters)
observe({
hei1<-input$heir1
hei2<-input$heir2
hei3<-input$heir3
choice1<-c("NONE",setdiff(heirarchy,c(hei2,hei3)))
choice2<-c("NONE",setdiff(heirarchy,c(hei1,hei3)))
choice3<-c("NONE",setdiff(heirarchy,c(hei1,hei2)))
updateSelectizeInput(session,"heir1",choices=choice1,selected=hei1)
updateSelectizeInput(session,"heir2",choices=choice2,selected=hei2)
updateSelectizeInput(session,"heir3",choices=choice3,selected=hei3)
})
}
shinyApp(ui, server)
You can use any of the Selectize JS plugins via the options argument to selectizeInput().
Note only the first input is updated.
Here is the code:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic selectInput"),
dashboardSidebar(
sidebarMenu(
menuItemOutput("menuitem")
)
),
dashboardBody(
selectizeInput("heir1","Heirarchy1",c("NONE",letters),selected="NONE",
# use this syntax to bring in selectize.js plugins :)
options = list(plugins = list('restore_on_backspace'))),
selectizeInput("heir2","Heirarchy2",c("NONE",letters),selected="NONE"),
selectizeInput("heir3","Heirarchy3",c("NONE",letters),selected="NONE")
)
)
server <- function(input, output, session) {
output$menuitem <- renderMenu({
menuItem("Menu item", icon = icon("calendar"))
})
heirarchy<-c(letters)
observe({
hei1<-isolate(input$heir1) # don't allow re-evaluation as users type
hei2<-input$heir2
hei3<-input$heir3
choice1<-c("NONE",setdiff(heirarchy,c(hei2,hei3)))
choice2<-c("NONE",setdiff(heirarchy,c(hei1,hei3)))
choice3<-c("NONE",setdiff(heirarchy,c(hei1,hei2)))
updateSelectizeInput(session,"heir1",choices=choice1,selected=hei1)
updateSelectizeInput(session,"heir2",choices=choice2,selected=hei2)
updateSelectizeInput(session,"heir3",choices=choice3,selected=hei3)
})
}
shinyApp(ui, server)
Note that isolate() is necessary to prevent updateSelectizeeInput() from being re-called and messing everything up as your users type.
EDIT:
Sorry mate, misread your desired behavior when I answered. I think you will get what you want if you remove the options =, but keep the isolate().
selectizeInput("heir1","Heirarchy1",c("NONE",letters),selected="NONE")
It is the updateSelectizeInput() without isolate() that is causing the cursor to leave the input field and requiring your users to re-click after a deletion.
Let me know if that's not what you were describing. Cheers!

Resources