Is there any way to set shinydashboard menu to permanently expanded like on image below:
I know accordion menus behave like this (I mean only one can be expanded at the same time) due to documentation but maybe there is some trick to do this or some alternative to implement in my shiny app?
Here is code:
library(shiny)
library(shinydashboard)
header <- dashboardHeader()
sidebar <- dashboardSidebar(
sidebarMenu(
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets",
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2"),
startExpanded = TRUE),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 3", tabName = "subitem3"),
menuSubItem("Sub-item 4", tabName = "subitem4"),
startExpanded = TRUE
)
)
)
body <- dashboardBody(
tabItems(
tabItem("dashboard",
div(p("Dashboard tab content"))
),
tabItem("widgets",
"Widgets tab content"
),
tabItem("subitem1",
"Sub-item 1 tab content"
),
tabItem("subitem2",
"Sub-item 2 tab content"
)
)
)
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) { }
)
Ok, this is very hacky and there may be a better way to do this, but you can use CSS styling to move the links "below" the other content so they cant be clicked using z-index. Unfortunately it looks like you have to code each menu item by hand, referencing its href. Please see this example:
library(shiny)
library(shinydashboard)
header <- dashboardHeader()
sidebar <- dashboardSidebar(
sidebarMenu(
tags$head(tags$style(HTML('
a[href="#shiny-tab-widgets"] {
z-index: -99999;
}
a[href="#"] {
z-index: -99999;
}
'))),
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets",
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2"),
startExpanded = TRUE),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 3", tabName = "subitem3"),
menuSubItem("Sub-item 4", tabName = "subitem4"),
startExpanded = TRUE
)
)
)
body <- dashboardBody(
tabItems(
tabItem("dashboard",
div(p("Dashboard tab content"))
),
tabItem("widgets",
"Widgets tab content"
),
tabItem("subitem1",
"Sub-item 1 tab content"
),
tabItem("subitem2",
"Sub-item 2 tab content"
)
)
)
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) { }
)
Related
For convertMenuItem, see reference here: https://stackoverflow.com/a/48212169
When I try to get the name of expanded menuItem, it doesn't work. Here's a standalone example:
library(shiny)
library(shinydashboard)
convertMenuItem <- function(mi,tabName) {
mi$children[[1]]$attribs['data-toggle']="tab"
mi$children[[1]]$attribs['data-value'] = tabName
if(length(mi$attribs$class)>0 && mi$attribs$class=="treeview"){
mi$attribs$class=NULL
}
mi
}
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets"),
convertMenuItem(menuItem("Charts", tabName = "charts", icon = icon("bar-chart-o"), expandedName = "CHARTS",
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
), "charts")
),
textOutput("res")
),
dashboardBody(
tabItems(
tabItem("dashboard", "Dashboard tab content"),
tabItem("widgets", "Widgets tab content"),
tabItem("subitem1", "Sub-item 1 tab content"),
tabItem("subitem2", "Sub-item 2 tab content")
)
)
)
server <- function(input, output, session) {
output$res <- renderText({
req(input$sidebarItemExpanded)
paste("Expanded menuItem:", input$sidebarItemExpanded)
print(input$sidebarItemExpanded)
})
}
shinyApp(ui, server)
Is there a way to further modify this function so that Expanded Item functionality is also supported?
The following is a workaround to avoid using convertMenuItem.
Instead of it I'm using a hidden menuItem which is displayed once the childful menuItem "Charts" is expanded.
This way input$sidebarItemExpanded works as expected.
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
id = "sidebarID",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets"),
menuItem("Charts", tabName = "charts", icon = icon("bar-chart-o"), expandedName = "CHARTS",
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
),
hidden(menuItem("hiddenCharts", tabName = "hiddenCharts"))
),
textOutput("res")
),
dashboardBody(
useShinyjs(),
tabItems(
tabItem("dashboard", "Dashboard tab content"),
tabItem("widgets", "Widgets tab content"),
tabItem("hiddenCharts", "Charts Tab"),
tabItem("subitem1", "Sub-item 1 tab content"),
tabItem("subitem2", "Sub-item 2 tab content")
)
)
)
server <- function(input, output, session) {
observeEvent(input$sidebarItemExpanded, {
if(input$sidebarItemExpanded == "CHARTS"){
updateTabItems(session, "sidebarID", selected = "hiddenCharts")
}
})
output$res <- renderText({
req(input$sidebarItemExpanded)
paste("Expanded menuItem:", input$sidebarItemExpanded)
print(input$sidebarItemExpanded)
})
}
shinyApp(ui, server)
I am trying to have an action button within the Body of a tab (called "Widgets" in code) link to a different tab (called "data_table" in code). I know how to do this if the tab that I want to connect to, "data_table", is one of the menuItems that appears on the sidebarMenu. However, I do not wish for a link to the "data_table" tab to appear in the sidebar. I am stuck. I would have thought I need an "observeEvent"-type command which links the action button to the "data_table" tab. But I don't know what that is. Advice welcome. The code shows the UI side of things.
ui <- dashboardPage(
dashboardHeader(title = "My query"),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")),
tabItem(tabName = "widgets",
h2("Widgets"),
actionButton(inputId="seedata", label = "See data")),
tabItem(tabName = "data_table",
h2("Table with the data"))
)
)
)
server <- function(input, output, session) { }
shinyApp(ui, server)
Perhaps you are looking for something like this.
ui <- dashboardPage(
dashboardHeader(title = "My query"),
dashboardSidebar(
sidebarMenu(# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")),
tabItem(tabName = "widgets", h2("Widgets"),
fluidRow(
tabBox(id = "tabset1", height = "850px", width=12, title = "My Data",
### The id lets us use input$tabset1 on the server to find the current tab
tabPanel("Table with the data", value="tab1", " ",
actionButton(inputId="seedata", label = "See data"),
uiOutput("dataTable")
),
tabPanel("Display Data Table", value="tab2", " ",
#uiOutput("someoutput")
DT::dataTableOutput("testtable")
)
)
)
))
)
)
server <- function(input, output, session) {
output$dataTable <- renderUI({
tagList(
div(style="display: block; height: 350px; width: 5px;",HTML("<br>")),
actionBttn(inputId="datatable",
label="Data Table",
style = "simple",
color = "success",
size = "md",
block = FALSE,
no_outline = TRUE
))
})
observeEvent(input$datatable, {
updateTabItems(session, "tabs", "widgets")
if (input$datatable == 0){
return()
}else{
## perform other tasks if necessary
output$testtable <- DT::renderDataTable(
mtcars,
class = "display nowrap compact", # style
filter = "top", # location of column filters
options = list( # options
scrollX = TRUE # allow user to scroll wide tables horizontally
)
)
}
})
observeEvent(input$datatable, {
updateTabsetPanel(session, "tabset1",
selected = "tab2")
})
}
shinyApp(ui, server)
I would like to know why when a open a page (a1) in my shiny app and then I open another page (for example a2) then I can't come back to a1?
To reproduce my example please follow these steps:
click on a2
click on b1
click on c1
click on c8
click on c1 again
I would expect to see the content of c1 again ("example of text 2"), but clicking c1 again appears to do nothing.
library(shinydashboard)
library(shiny)
sidebar <- dashboardSidebar(
tags$head(tags$style(
HTML('.content-wrapper { height: 1500px !important;}')
)),
hr(),
sidebarMenu(
id = "tabs",
menuItem(
"a1",
tabName = "principal",
icon = icon("pagelines"),
selected = TRUE
),
menuItem(
"a2",
icon = icon("chart-bar"),
menuSubItem("b1", tabName = "identificacion", icon = icon("angle-right")),
menuSubItem("b2", tabName = "comunicacion", icon = icon("angle-right")),
menuSubItem("b3", tabName = "medicamentos", icon = icon("angle-right")),
menuSubItem("b4", tabName = "cirugias", icon = icon("angle-right")),
menuSubItem("b5", tabName = "infecciones", icon = icon("angle-right")),
menuSubItem("b6", tabName = "caidas", icon = icon("angle-right"))
),
menuItem("a3", tabName = "procesos", icon = icon("chart-bar")),
menuItem("a4", tabName = "tiempos", icon = icon("chart-bar")),
menuItem("a5", tabName = "manual", icon = icon("mortar-board")),
menuItem("a6", tabName = "acerca", icon = icon("question"))
),
width = 285,
hr(),
conditionalPanel("input.tabs=='identificacion'",
fluidRow(
column(1),
column(
10,
menuItem(
"c1",
tabName = "admision_iden",
icon = icon("chart-line"),
selected = FALSE
),
menuItem(
"c8",
tabName = "uci_iden",
icon = icon("chart-line"),
selected = FALSE
)
)
))
)
body <- dashboardBody(tabItems(
tabItem(tabName = "principal",
withMathJax(), ("example of text")),
tabItem(tabName = "admision_iden", titlePanel("example1"), "example of text 2"),
tabItem(tabName = "uci_iden", titlePanel("example 2"), "example of text 3")
))
ui <- dashboardPage(dashboardHeader(title = "Indic", titleWidth = 285),
sidebar,
body)
server <- function(input, output) {}
runApp(list(ui = ui, server = server))
Your additional menus are rendered outside sidebarMenu, so when selected, their ids are not recorded in the input variable input$tabs (which is what the app is monitoring). Including the menus inside sidebarMenu allows the tabItems to track the menuItems, but also breaks the reactivity, i.e., when input$tabs == 'uci_iden' the additional menus disappear (because input$tabs != 'identificacion').
One way to achieve the behavior you want (possibly not the best way) is to render the additional menus through the server using renderUI. Note that we still have to include the additional menus inside sidebarMenu and monitor them through input$tabs. To make sure they stick around when input$tabs != 'identificacion', we can include their ids in the condition. When neither of identification, uni_iden or admision_iden are selected, we render an empty div.
Updated code:
library(shinydashboard)
library(shiny)
sidebar <- dashboardSidebar(
tags$head(tags$style(
HTML('.content-wrapper { height: 1500px !important;}')
)),
hr(),
sidebarMenu(
id = "tabs",
menuItem(
"a1",
tabName = "principal",
icon = icon("pagelines"),
selected = TRUE
),
menuItem(
"a2",
icon = icon("chart-bar"),
menuSubItem("b1", tabName = "identificacion", icon = icon("angle-right")),
menuSubItem("b2", tabName = "comunicacion", icon = icon("angle-right")),
menuSubItem("b3", tabName = "medicamentos", icon = icon("angle-right")),
menuSubItem("b4", tabName = "cirugias", icon = icon("angle-right")),
menuSubItem("b5", tabName = "infecciones", icon = icon("angle-right")),
menuSubItem("b6", tabName = "caidas", icon = icon("angle-right"))
),
menuItem("a3", tabName = "procesos", icon = icon("chart-bar")),
menuItem("a4", tabName = "tiempos", icon = icon("chart-bar")),
menuItem("a5", tabName = "manual", icon = icon("mortar-board")),
menuItem("a6", tabName = "acerca", icon = icon("question")),
width = 285,
hr(),
uiOutput("more_menus")
)
)
body <- dashboardBody(tabItems(
tabItem(tabName = "principal",
withMathJax(), ("example of text")),
tabItem(tabName = "admision_iden", titlePanel("example1"), "example of text 2"),
tabItem(tabName = "uci_iden", titlePanel("example 2"), "example of text 3")
))
ui <- dashboardPage(dashboardHeader(title = "Indic", titleWidth = 285),
sidebar,
body)
server <- function(input, output) {
make_menus <- reactive({
if (req(input$tabs) %in% c("identificacion", "admision_iden", "uci_iden")) {
fluidRow(column(1),
column(
10,
menuItem(
"c1",
tabName = "admision_iden",
icon = icon("chart-line"),
selected = FALSE
),
menuItem(
"c8",
tabName = "uci_iden",
icon = icon("chart-line"),
selected = FALSE
)
))
} else {
div()
}
})
output$more_menus <- renderUI({ make_menus() })
}
runApp(list(ui = ui, server = server))
I'm using a shinydashboard but when the title is too long it fails to wrap the lines. I have tried using <br/> to accomplish this, but it doesn't work even with HTML() around it in this context.
I know I can make the title space wider with titleWidth, but that does not look as good in many cases.
What would be the simplest way to achieve this?
Here's an example:
library(shiny)
library(shinydashboard)
## Only run this example in interactive R sessions
if (interactive()) {
header <- dashboardHeader(title = "This title is just way too long")
sidebar <- dashboardSidebar(
sidebarUserPanel("User Name",
subtitle = a(href = "#", icon("circle", class = "text-success"), "Online"),
# Image file should be in www/ subdir
image = "userimage.png"
),
sidebarSearchForm(label = "Enter a number", "searchText", "searchButton"),
sidebarMenu(
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets", badgeLabel = "new",
badgeColor = "green"),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
)
)
)
body <- dashboardBody(
tabItems(
tabItem("dashboard",
div(p("Dashboard tab content"))
),
tabItem("widgets",
"Widgets tab content"
),
tabItem("subitem1",
"Sub-item 1 tab content"
),
tabItem("subitem2",
"Sub-item 2 tab content"
)
)
)
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) { }
)
}
The goal is to apply word-wrapping so that we can read the entire title (which says "This title is just way too long").
header <- dashboardHeader(title = h4(HTML("This title<br/>is just way too long")))
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) { }
)
So I need to create action buttons in R shiny based on the number of rows in dataframe, upon googling for the solution now able to create the action buttons dynamically but I was not able to label it according to the values in the data frame.
Here is my UI.R
library(shiny)
library(shinydashboard)
library(DT)
shinyUI(
dashboardPage(
dashboardHeader(title = div(img(src="new.png", height = 40, width = 200),"IPT dashboard",width = 300)),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Vehicle Data", tabName = "VehicleData", icon = icon("table")),
menuItem("Driver Behaviour", tabName = "DriverBehaviour", icon = icon("th")),
menuItem("Vehicle Information", tabName = "Vehicleinfo", icon = icon("th")),
menuItem("Crash Report", tabName = "crashreport", icon = icon("th")),
menuItem("Emission Report", tabName = "Emissionreport", icon = icon("th")),
menuItem("Fuel Economy", tabName = "FuelEconomy", icon = icon("th")),
menuItem("View Location", tabName = "viewloc", icon = icon("th")),
menuItem("detctest", tabName = "dtctest", icon = icon("th"))
),
width = "200px"
),
dashboardBody(
tabItems(
tabItem("dashboard",
tabsetPanel(
tabPanel( title = "Real Time",
br(),
fluidRow(
box(
tags$head(
tags$style(HTML("
.box { overflow-y: auto; }
" )
)
),
height = "300px",
width =2,
h3("Trouble Code(s)", align="left"),
column(1, uiOutput("go_buttons"))
)
)#tabitemsclose
)#dashbodyclose
)#pageclose
)#uiclose
Server.R
library(shiny)
library(DT)
shinyServer(function(input,output)
{
options(digits = 22)
output$go_buttons <- renderUI({
mat <- as.data.frame(c("P01","p02","p03"))
buttons <- as.list(1:ncol(mat))
buttons <- lapply(buttons, function(i)
{
btName <- paste0(mat[i])
fluidRow(
br(),
column(2,actionButton(btName,paste(mat[i])))
)
})
})
When I execute the above scripts, It shows only one action button with the values as in the dataframe.
Expected output
Here in Server.R I am creating dataframe but in real time I will be fetching it through other calculation where the number of rows is not fixed which implies the number of action buttons are also not predefined, Number of action button will be equal to the number of rows in the data frame also, the label of action button should be same as the values in the data frame.
You only get one action button out, because your apply loop only has one number in it. You take 1:ncol(mat) eventhough your data.frame has only one column.
I changed two things:
I replaced buttons inside the lapply-function with 1:nrow(mat)
I used mat[i,1] because your values are in the rows. If in your data the values you want on the action buttons are in one vector you can keep using [i]
The app.r:
library(shiny)
library(shinydashboard)
library(DT)
### ui.r
ui <- shinyUI(dashboardPage(
dashboardHeader(title = div(img(src="new.png", height = 40, width = 200),"IPT dashboard",width = 300)),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Vehicle Data", tabName = "VehicleData", icon = icon("table")),
menuItem("Driver Behaviour", tabName = "DriverBehaviour", icon = icon("th")),
menuItem("Vehicle Information", tabName = "Vehicleinfo", icon = icon("th")),
menuItem("Crash Report", tabName = "crashreport", icon = icon("th")),
menuItem("Emission Report", tabName = "Emissionreport", icon = icon("th")),
menuItem("Fuel Economy", tabName = "FuelEconomy", icon = icon("th")),
menuItem("View Location", tabName = "viewloc", icon = icon("th")),
menuItem("detctest", tabName = "dtctest", icon = icon("th"))
),
width = "200px"
),
dashboardBody(tabItems(
tabItem("dashboard",
tabsetPanel(
tabPanel( title = "Real Time",
br(),
fluidRow(
box(
tags$head(
tags$style(HTML("
.box { overflow-y: auto; }
" )
)
),
height = "300px",
width =2,
h3("Trouble Code(s)", align="left"),
column(1, uiOutput("go_buttons"))
)))))
) #tabitemsclose
)#dashbodyclose
)#pageclose
) #uiclose
### server.r
server <- function(input, output, session){
options(digits = 22)
output$go_buttons <- renderUI({
mat <- as.data.frame(c("P01","p02","p03"),stringsAsFactors = FALSE)
buttons <- lapply(1:nrow(mat), function(i)
{
btName <- paste0(mat[i,1])
fluidRow(
br(),
column(2,actionButton(btName,paste(mat[i,1])))
)
})
return(buttons)
})
}
shinyApp(ui, server)