toggle controlbar based on tab and action button - r

I'm trying to toggle the control bar using an actionLink in the top right (to basically copy what the gears icon is doing, and later I will remove the gears icon to just have one actionLink) and also to automate the toggling such that when the user clicks on feedback, the controlbar disappears and reappears when the user clicks on any other tab. I also want to make sure throughout this toggling, the controlbar does not overlay on the dashboard body (basically the dashboard body will resize appropriately whenever the control bar toggles).
This is what I've tried so far:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
ui <- dashboardPage(
title = 'Test',
header = dashboardHeader(
title = span("Test"),
titleWidth = 600,
tags$li(
id = 'right-sidebar-toggle-list-item',
class = "dropdown",
actionLink("rightSidebarToggle", "Select Population"))
), # end of dashboardheader
sidebar = dashboardSidebar(
sidebarMenu(id = "sidebar",
menuItem("Overview", tabName = "introduction", icon = icon("info")),
menuItem("Feedback", tabName = "feedback", icon = icon("info")))),
body = dashboardBody(plotOutput("cars")),
controlbar = dashboardControlbar(
id = "controlbar",
width = 270,
skin = "light",
collapsed = F,
overlay = F,
controlbarMenu(
id = "menu",
controlbarItem(
' ',
# - select study
checkboxGroupButtons(
inputId = "select_study",
label = "Select Study",
choiceNames = c("1", "2"),
choiceValues = c("1", "2"),
selected = c("1", "2"),
justified = TRUE,
status = "primary",
direction = "vertical",
checkIcon = list(yes = icon("ok", lib = "glyphicon"))
),
)
)
)
)
server <- function(input, output, session) {
output$cars <- renderPlot({
plot(mtcars)
})
# event to toggle right sidebar menu
observeEvent(input$rightSidebarToggle, {
shinyjs::toggleClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
})
##### > Controlbar Collapse #####
observeEvent(input[["sidebar"]], {
if(input[["sidebar"]] == "feedback"){
removeClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
}else{
addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
updateControlbar("controlbar")
}
})
}
shinyApp(ui, server)

There is no need to create a new actionLink and hide the existing a-tag. We can simply modify it.
Please check the following:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
ui <- dashboardPage(
title = 'Test',
header = dashboardHeader(
title = span("Test"),
titleWidth = 600,
controlbarIcon = NULL
),
sidebar = dashboardSidebar(sidebarMenu(
id = "sidebar",
menuItem("Overview", tabName = "introduction", icon = icon("info")),
menuItem("Feedback", tabName = "feedback", icon = icon("info"))
)),
body = dashboardBody(
useShinyjs(),
tags$script(
HTML(
"var el = document.querySelector('body > div > header > nav > div:nth-child(4) > ul > li:last-child > a');
el.innerHTML = 'Select Population';"
)
),
plotOutput("cars")
),
controlbar = dashboardControlbar(
id = "controlbar",
width = 270,
skin = "light",
collapsed = FALSE,
overlay = FALSE,
controlbarMenu(id = "menu",
controlbarItem(' ',
checkboxGroupButtons(
inputId = "select_study",
label = "Select Study",
choiceNames = c("1", "2"),
choiceValues = c("1", "2"),
selected = c("1", "2"),
justified = TRUE,
status = "primary",
direction = "vertical",
checkIcon = list(yes = icon("ok", lib = "glyphicon"))
)
)
)
)
)
server <- function(input, output, session) {
output$cars <- renderPlot({
plot(mtcars)
})
observeEvent(input[["sidebar"]], {
if (input[["sidebar"]] == "feedback") {
removeClass(selector = "body", class = "control-sidebar-open")
shinyjs::runjs('Shiny.setInputValue(id = "controlbar", value = false);
$(window).trigger("resize");')
} else {
addClass(selector = "body", class = "control-sidebar-open")
shinyjs::runjs('Shiny.setInputValue(id = "controlbar", value = true);
$(window).trigger("resize");')
}
}, ignoreInit = FALSE)
}
shinyApp(ui, server)
Edit: Here is an UI-only approach not using library(shinyjs):
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
ui <- dashboardPage(
title = 'Test',
header = dashboardHeader(
title = span("Test"),
titleWidth = 600,
controlbarIcon = NULL
),
sidebar = dashboardSidebar(sidebarMenu(
id = "sidebar",
menuItem("Overview", tabName = "introduction", icon = icon("info")),
menuItem("Feedback", tabName = "feedback", icon = icon("info"))
)),
body = dashboardBody(
tags$script(
HTML(
"var el = document.querySelector('body > div > header > nav > div:nth-child(4) > ul > li:last-child > a');
el.innerHTML = 'Select Population';
$(document).on('shiny:connected', function(event) {
$(window).trigger('resize'); // resize once on session start - needed when using collapsed = FALSE
});
$(document).on('shiny:inputchanged', function(event) {
if (event.name === 'sidebar') {
if (event.value === 'feedback') {
document.querySelector('body').classList.remove('control-sidebar-open');
Shiny.setInputValue(id = 'controlbar', value = false);
$(window).trigger('resize');
} else {
document.querySelector('body').classList.add('control-sidebar-open');
Shiny.setInputValue(id = 'controlbar', value = true);
$(window).trigger('resize');
}
}
});"
)
),
plotOutput("cars")
),
controlbar = dashboardControlbar(
id = "controlbar",
width = 270,
skin = "light",
collapsed = FALSE,
overlay = FALSE,
controlbarMenu(id = "menu",
controlbarItem(' ',
checkboxGroupButtons(
inputId = "select_study",
label = "Select Study",
choiceNames = c("1", "2"),
choiceValues = c("1", "2"),
selected = c("1", "2"),
justified = TRUE,
status = "primary",
direction = "vertical",
checkIcon = list(yes = icon("ok", lib = "glyphicon"))
)
)
)
)
)
server <- function(input, output, session) {
output$cars <- renderPlot({
plot(mtcars)
})
}
shinyApp(ui, server)

Related

Change the size of an icon in shiny dashboard

How can I change the size of an icon() in shiny dashboard?
library(shiny)
library(shinydashboardPlus)
shinyApp(
ui = dashboardPage(skin = "purple",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(
controlbarIcon = shiny::icon("filter")
),
sidebar = dashboardSidebar(),
body = dashboardBody(
tags$style(".fa-filter {color:red;size:26px}"),
),
controlbar = dashboardControlbar(
id = "controlbar",
collapsed = FALSE,
overlay = TRUE,
skin = "light",
pinned = T
)
),
server = function(input, output, session) {
}
)
You have to set the CSS property font-size instead of size:
library(shiny)
library(shinydashboardPlus)
shinyApp(
ui = dashboardPage(
skin = "purple",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(
controlbarIcon = shiny::icon("filter")
),
sidebar = dashboardSidebar(),
body = shinydashboard::dashboardBody(
tags$style(".fa-filter {color:red; font-size:26px}"),
),
controlbar = dashboardControlbar(
id = "controlbar",
collapsed = FALSE,
overlay = TRUE,
skin = "light",
pinned = T
)
),
server = function(input, output, session) {
}
)
#>
#> Listening on http://127.0.0.1:6563
Below please find two alternative ways not requiring a separate style tag:
library(shiny)
library(fontawesome)
shinyApp(
basicPage(
shiny::icon("filter", class = "fa-3x"),
fontawesome::fa("filter", height = "3em")
),
server = function(input, output, session) {
}
)
Furthermore, please check this related article.
Using your example:
library(shiny)
library(shinydashboardPlus)
shinyApp(
ui = dashboardPage(
skin = "purple",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(
controlbarIcon = shiny::icon("filter", class = "fa-3x", style = "color:red;")
# controlbarIcon = fontawesome::fa("filter", height = "3em", fill = "red")
),
sidebar = dashboardSidebar(),
body = shinydashboard::dashboardBody(),
controlbar = dashboardControlbar(
id = "controlbar",
collapsed = FALSE,
overlay = TRUE,
skin = "light",
pinned = T
)
),
server = function(input, output, session) {
}
)

remove toggle gear icon controlbar

I'm trying to customize how my R shiny app looks like and playing around with various elements on the page.
Just wondering how do I remove this toggle icon from the header? I've tried something like this but it doesn't work:
shinyjs::runjs("document.getElementsByClassName('skin-blue sidebar-mini')[0].style.visibility = 'hidden';")
reproducible example:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyjs)
library(DT)
ui <- shinydashboardPlus::dashboardPage(
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(
tags$li(
id = 'right-sidebar-toggle-list-item',
class = "dropdown",
actionLink("rightSidebarToggle", "Select Population"))
),
shinydashboardPlus::dashboardSidebar( disable = TRUE ,
sidebarMenu(
selectInput(
"countries", label = "Select Countries",
choices = c("B", "C", "A"), selected = "A",
multiple = TRUE
))
),# minified = TRUE, collapsed = F),
controlbar = shinydashboardPlus::dashboardControlbar(id = "controlbar", collapsed = F,
skin = "dark",
controlbarMenu(
id = "menu",
controlbarItem(
"Tab 1",
"Welcome to tab 1"
),
controlbarItem(
"Tab 2",
"Welcome to tab 2"
)
)
),
shinydashboard::dashboardBody(
useShinyjs(),
tabsetPanel( id="tabset",
tabPanel("Resource Allocation", value="tab1", plotOutput("plot")),
)
),
# controlbar = dashboardControlbar(collapsed = F),
title = "DashboardPage"
)
server <- function(input, output) {
output$plot <- renderPlot(plot(cars))
}
shinyApp(ui, server)
We can use some JS via tags$script to hide the icon:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyjs)
library(DT)
ui <- shinydashboardPlus::dashboardPage(
options = list(sidebarExpandOnHover = TRUE),
shinydashboardPlus::dashboardHeader(
tags$li(
id = 'right-sidebar-toggle-list-item',
class = "dropdown",
actionLink("rightSidebarToggle", "Select Population"))
),
shinydashboardPlus::dashboardSidebar(disable = TRUE ,
sidebarMenu(
selectInput(
"countries",
label = "Select Countries",
choices = c("B", "C", "A"),
selected = "A",
multiple = TRUE
)
)),
# minified = TRUE, collapsed = F),
controlbar = shinydashboardPlus::dashboardControlbar(
id = "controlbar",
collapsed = F,
skin = "dark",
controlbarMenu(
id = "menu",
controlbarItem("Tab 1",
"Welcome to tab 1"),
controlbarItem("Tab 2",
"Welcome to tab 2")
)
),
shinydashboard::dashboardBody(
useShinyjs(),
# hide icon
# tags$script(
# HTML(
# 'var e = document.querySelector("body > div.wrapper > header > nav > div:nth-child(4) > ul > li > a > i");
# e.setAttribute("style", "display: none;");'
# )
# ),
# hide hyperlink
tags$script(HTML('var e = document.querySelector("body > div.wrapper > header > nav > div:nth-child(4) > ul > li:last-child > a");
e.setAttribute("style", "display: none;");')),
tabsetPanel(
id = "tabset",
tabPanel("Resource Allocation", value = "tab1", plotOutput("plot")),
)
),
# controlbar = dashboardControlbar(collapsed = F),
title = "DashboardPage"
)
server <- function(input, output) {
output$plot <- renderPlot(plot(cars))
}
shinyApp(ui, server)

Generate dynamic Tab using argonDash (shiny framework) package

I tried to make dynamic Tab using argonDash package. However, I met some trouble with my code.
I guess argonDash seems to get different behavior than native shiny because argonDash uses Bootstrap 4 (instead of 3).
My code is composed of two key features:
The first widget uiOutput(outputId = "new_argonSidebarItem") works well.
The second widget uiOutput(outputId = "new_argonTabItem") doesn't work properly. I expect that the argonBadge() toggle with the second tab.
library(shiny)
library(argonDash)
library(argonR)
ui <- argonDashPage(
sidebar = argonDashSidebar(
id = "sidebar01",
vertical = FALSE,
size = "md",
background = "white",
argonSidebarMenu(
style = "display:-webkit-inline-box;",
argonSidebarItem(
tabName = "Tab1",
icon = NULL,
"Dashboard"
),
# New Tab
uiOutput(outputId = "new_argonSidebarItem")
)
),
body = argonDashBody(
argonTabItems(
argonTabItem(
tabName = "Tab1",
actionButton("add_more", "Add a new btn")
),
# Body
uiOutput(outputId = "new_argonTabItem")
)
)
)
server <- function(input, output, session) {
observeEvent(input$add_more, {
tabId <- sample.int(n = 1000000, size = 1)
tabName <- paste0("Tab_", tabId)
insertUI(
selector = "#tab-Tab1",
where = "afterEnd",
ui = argonSidebarItem(
tabName = tabName,
tabName
)
)
output$new_argonTabItem <- renderUI({
argonTabItem(
tabName = tabName,
argonBadge(
text = tabName,
src = "#",
pill = FALSE,
status = "success"
)
)
})
})
}
shinyApp(ui, server)
Thank you for your time!
To update your badge you need to track which tab is selected. This is done accordingly to this solution : https://github.com/RinteRface/argonDash/issues/7
But your badge can not be modified, so I replaced it with a button from {shinyWidgets}.
I hope this is what you ask for, I'm not really sure to understand what you want to happen.
library(shiny)
library(argonDash)
library(argonR)
library(shinyWidgets)
ui <- argonDashPage(
sidebar = argonDashSidebar(
id = "sidebar01",
vertical = FALSE,
size = "md",
background = "white",
argonSidebarMenu(
style = "display:-webkit-inline-box;",
argonSidebarItem(
tabName = "Tab1",
icon = NULL,
"Dashboard"
),
# New Tab
uiOutput(outputId = "new_argonSidebarItem")
)
),
body = argonDashBody(
argonTabItems(
argonTabItem(
tabName = "Tab1",
actionButton("add_more", "Add a new btn")
),
# Body
uiOutput(outputId = "new_argonTabItem")
),
tags$script( "$(document).on('click', function(event) {
Shiny.onInputChange('activeTab', $('.active').data().value);});")
)
)
server <- function(input, output, session) {
x <- reactiveValues(tabs = NULL)
observeEvent(input$add_more, {
tabId <- sample.int(n = 1000000, size = 1)
tabName <- paste0("Tab_", tabId)
insertUI(
selector = "#tab-Tab1",
where = "afterEnd",
ui = argonSidebarItem(
tabName = tabName,
tabName
)
)
output$new_argonTabItem <- renderUI({
argonTabItem(
tabName = tabName,
actionBttn(
inputId = paste0(input$activeTab,"_b"),
label = tabName,
style = "float",
color = "success"
)#,
# argonBadge(
# text = tabName,
# src = "#",
# pill = FALSE,
# status = "success"
# )
)
})
})
observeEvent(input$activeTab, {
updateActionButton(session,
paste0(input$activeTab,"_b"),
input$activeTab)
})
}
shinyApp(ui, server)

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.
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.

Hide and show sidebars based on chosen tabPanel in shinydashboard

I have the shinydashboard below in which I have 3 tabPanels. In the 1st tabPanel "Resource Allocation" I want the left and right sidebar open by default. In the 2nd and 3rd tabpanels ("Time Series","Longitudinal View") I want only left sidebar and the right sidebar not just hidden but to not be able to open at all by pushing the "gears" icon above it which should be removed. And in the fourth panel "User Guide" I want no sidebar and no choise to open one of them at all.
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyjs)
shinyApp(
ui = dashboardPage(
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(
titleWidth = "0px"
),
sidebar = dashboardSidebar(minified = TRUE, collapsed = F),
body = dashboardBody(
useShinyjs(),#tags$head(tags$script(src="format_number.js")),
tags$script("document.getElementsByClassName('sidebar-toggle')[0].style.visibility = 'hidden';"),
tabsetPanel(
tabPanel("Resource Allocation"),
tabPanel("Time Series"),
tabPanel("Longitudinal View"),
tabPanel("User Guide")
)
),
controlbar = dashboardControlbar(collapsed = F),
title = "DashboardPage"
),
server = function(input, output) { }
)
I have a solution for the left sidebar. I am sure you can spend sometime and figure out the solution for the right sidebar. Please note that this requires some more work to fine tune to your needs. Try this
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyjs)
library(DT)
ui <- shinydashboardPlus::dashboardPage(
options = list(sidebarExpandOnHover = TRUE),
shinydashboardPlus::dashboardHeader(
#titleWidth = "0px"
),
shinydashboardPlus::dashboardSidebar( disable = TRUE ,
sidebarMenu(
selectInput(
"countries", label = "Select Countries",
choices = c("B", "C", "A"), selected = "A",
multiple = TRUE
))
),# minified = TRUE, collapsed = F),
controlbar = shinydashboardPlus::dashboardControlbar(id = "controlbar", collapsed = F,
skin = "dark",
controlbarMenu(
id = "menu",
controlbarItem(
"Tab 1",
"Welcome to tab 1"
),
controlbarItem(
"Tab 2",
"Welcome to tab 2"
)
)
),
shinydashboard::dashboardBody(
useShinyjs(),
tabsetPanel( id="tabset",
tabPanel("Resource Allocation", value="tab1", plotOutput("plot")),
tabPanel("Time Series", value="tab2", plotOutput("plot2")),
tabPanel("Longitudinal View", value="tab3", DTOutput("ir")),
tabPanel("User Guide", value="tab4", DTOutput("mt"))
)
),
# controlbar = dashboardControlbar(collapsed = F),
title = "DashboardPage"
)
server <- function(input, output) {
output$plot <- renderPlot(plot(cars))
output$plot2 <- renderPlot(plot(pressure))
output$mt <- renderDT(mtcars)
output$ir <- renderDT(iris)
observeEvent(input[["tabset"]], {
if(input[["tabset"]] == "tab4"){
addClass(selector = "body", class = "sidebar-collapse")
updateControlbar("controlbar")
}else{
removeClass(selector = "body", class = "sidebar-collapse")
}
})
}
shinyApp(ui, server)

Resources