dropdownButton alignment within dashboardSidebar - r

I'm using the dropdownButton function from this link drop-down checkbox input in shiny that is in shinyWidgets, with a slight modification so that the text is black.
I want the dropdownButton to look like the selectInput drop down I have above it as much as possible. I got them to line up in the sidebar with column(1,) function, but I also want the width of the dropdownButton to be the same width as the selectInput.
I also got the width of the dropdown choices to be the same width of the selectInput above it with width=200, but I want the dropdown button to also be the same size.
Can someone help me modify the dropDownButton function or my UI so that this is the case?
library(shiny)
library(shinydashboard)
dropdownButton2 <- function(label = "", status = c("default", "primary", "success", "info", "warning", "danger"), ..., width = NULL) {
status <- match.arg(status)
# dropdown button content
html_ul <- list(
class = "dropdown-menu",
style = if (!is.null(width))
paste0("width: ", validateCssUnit(width), ";"),
lapply(X = list(...), FUN = tags$li, style = "margin-left: 10px; margin-right: 10px;color:black")
)
# dropdown button apparence
html_button <- list(
class = paste0("btn btn-", status," dropdown-toggle"),
type = "button",
` data-toggle` = "dropdown"
)
html_button <- c(html_button, list(label))
html_button <- c(html_button, list(tags$span(class = "caret")))
# final result
tags$div(
class = "dropdown",
do.call(tags$button, html_button),
do.call(tags$ul, html_ul),
tags$script(
"$('.dropdown-menu').click(function(e) {
e.stopPropagation();
});")
)
}
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(width = 325,
selectInput('month',label='Filter 1:',choices= month.name,multiple = FALSE,selected = "March"),
br(),
column(1,
h5(strong(("Filter 2:"))),
dropdownButton2(
label = "Filter 2:", status = "default", width = 200,#circle = FALSE,
checkboxGroupInput(inputId = "check1", label = "Choose", choices = c("A","B","C"))
)
)),
dashboardBody()
)
server <- function(input, output){
}
shinyApp(ui = ui, server = server)

You can do so by adding the css tag tags$style(type = 'text/css', ".btn-default{width: 275px;}") in your ui code as below:
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(width = 325,
selectInput('month',label='Filter 1:',choices= month.name,multiple = FALSE,selected = "March"),
br(),
column(1,
h5(strong(("Filter 2:"))),
tags$style(type = 'text/css', ".btn-default{width: 275px;}"),
dropdownButton2(
label = "Filter 2:", status = "default", width = 200,#circle = FALSE,
checkboxGroupInput(inputId = "check1", label = "Choose", choices = c("A","B","C"))
)
)),
dashboardBody()
)
On adding the tag you get something like this:
[EDIT]:
I later realized that the caret was not right aligned as in the case of selectInput hence to align that I further added couple of css tags as follows:
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(width = 325,
selectInput('month',label='Filter 1:',choices= month.name,multiple = FALSE,selected = "March"),
br(),
column(1,
h5(strong(("Filter 2:"))),
tags$style(type = 'text/css', ".btn-default{width: 275px;}"),
tags$style(type = 'text/css', ".btn .caret{position: relative;}"),
tags$style(type = 'text/css', ".caret{top: 45%; right:-35%}"),
dropdownButton2(
label = "Filter 2:", status = "default", width = 200,#circle = FALSE,
checkboxGroupInput(inputId = "check1", label = "Choose", choices = c("A","B","C"))
)
)),
dashboardBody()
)
The additional tags resulted the caret to be aligned as follows:

Related

Reactivity and Renders doesn't work when switching to another tabPanel

I have a reproducible example below where only the first tabPanel is working, however when I switch to another panel, I don't get any renders (the toggle becomes un-interactable also). I have looked into conditionalPanel however I see them getting done without the use of mainPanel I was wondering if it possible to have tabs where each tab has its own mainPanel , so I can see a different sidebar and an output contained within different tabs. Any help is welcome!
options(scipen = 99999) #converts the sci numbers to their regular format
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinyalert)
library(esquisse)
library(DT)
library(dplyr)
#library(devtools)
#library(remotes)
#remotes::install_github("dreamRs/esquisse")
library(hrbrthemes)
library(ggthemes)
library(ggplot2)
library(svglite)
ui <- fluidPage(
shinyjs::useShinyjs(), # enables javascript/jQuery enhanchments
# Create Right Side Text
navbarPage(
title= div(HTML("G<em>T</em>")),
#General reports
tabPanel("General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "Text coming soon."
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel2_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse2",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
# monthly reports
tabPanel("Extra General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 3,
"mtcars"= 4),
icon= icon("check"),
selected = 3,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel3", "Text coming soon."
),
tabPanelBody(
"panel4",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel4_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse4",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;
font-family: "serif";')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2 = iris,
df3 = data.frame(),
df4 = mtcars)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
# modules only need to be called it once but individually for esquisse
esquisse::esquisse_server(id = "esquisse2", data_rv = data_to_use)
esquisse::esquisse_server(id = "esquisse4", data_rv = data_to_use)
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
req(input$controller)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum. Use server = FALSE to get full table
output[[paste0('panel', input$controller, '_data')]] <- DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons')})
})
}
#runs the app
shinyApp(ui= ui, server= server)
You have two radioButtons, one for each sidebar, but both of them have the inputId = "controller". Same with inputId = "toggleSidebar". InputIds need to be unique in shiny!
I suggest you either use a single sidebar for the entire app, or since both tabs are essentially identical you can also use modules.

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)

selectInput reactive value in shinyDashboard sidebar of R shiny app remains Null

It appears the input value of a selectInput object is not updating. I have inserted one in the sidebar menu. I am using shinyDashboard. here is my code.
header & Sidebar
header <-
dashboardHeader(
title = "REPORT",
tags$li(class = "dropdown",
tags$style(
HTML(
"#import url('//fonts.googleapis.com/css?family=Libre+Baskerville:400,700|Open+Sans:400,700|Montserrat:400,700');"
)
)),
disable = FALSE,
titleWidth = '200'
)
header$children[[3]]$children[[3]] <-
tags$h1("DATABASE",
# align = 'left',
style = "color:#FFFFFF; font-weight: bold; font-family: 'Open Sans','Libre Baskerville',Montserrat, serif;font-size: 23px;")
data_type_list<-c('in vivo','in vitro','pbpk')
siderbar <- dashboardSidebar(
width = 200,
sidebarMenu(
id = 'sidebar',
style = "position: relative; overflow: visible;",
menuItem(
"TK Knowlegebase",
tabName = 'tk',
icon = icon('database'),
badgeColor = "teal",
#radioButtons("tk_data_type", "Select Data Type:",data_type_list)
selectInput('tk_data_type',"Select Data Type",data_type_list, selected=1)
)
)
)
body
body <- dashboardBody(width = 870,
tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "custom.css")
),
#theme = shinythemes::shinytheme("darkly"),
tabItems(
tabItem (
tabName = "tk",
mainPanel(
#in vivo ----
conditionalPanel(
condition ="input.tk_data_type== 'in vivo'",
tags$h2('vivo')
),
# in vitro ----
conditionalPanel(
condition="input.tk_data_type== 'in vitro'",
tags$h2('vitro')
)
,
# pbpk ----
conditionalPanel(
condition="input.tk_data_type== 'pbpk'",
tags$h2('pbpk')
)
)))
server = function(input, output, session) {
observe({input$tk_data_type})
}
ui <- dashboardPage(title = 'ARC Toxkin App', skin = 'purple',
header, siderbar, body)
shiny::shinyApp(ui = ui, server = server)
I even attempted to use observe({input$tk_data_type}) in the server section to no success.
What I obtain is a blank page. what I wish to see is content from dashboardBody() appear.
Thank you for your time
UPDATE
This is a short-term fix solution, thanks to user YBS.
vitro_tabset<-tabsetPanel(
tabPanel("Detailed",
"This is a test"),
tabPanel("Phys-chem",
"This is a test"),
tabPanel("Exploratory",
"This is a test"),
tabPanel("Downloads",
"This is a test")
)
vivo_tabset<-tabsetPanel(
tabPanel("Detailed",
"This is a test"),
tabPanel("Phys-chem",
"This is a test"),
tabPanel("Exploratory",
"This is a test"),
tabPanel("Downloads",
"This is a test")
)
siderbar <- dashboardSidebar(
sidebarMenu(
id = 'sidebar',
menuItem(
"TK Knowlegebase",
tabName = 'tk',
icon = icon('database'),
badgeColor = "teal",
selected = TRUE,
startExpanded = TRUE,
#radioButtons("tk_data_type2", "Select Data Type:",data_type_list),
menuSubItem('vivo', tabName = 'vivo', icon = shiny::icon("angle-double-right"), selected = NULL),
menuSubItem('vitro', tabName = 'vitro', icon = shiny::icon("angle-double-right"), selected = TRUE),
menuSubItem('pbpk', tabName = 'pbpk', icon = shiny::icon("angle-double-right"), selected = NULL)
)
)
)
body <- dashboardBody(width = 870,
tabItems(
tabItem (tabName = "vivo",
vivo_tabset),
tabItem(tabName='vitro',
# in vitro ----
vitro_tabset),
# pbpk ----
tabItem(tabName='pbpk')
It appears that tabItems() and tabItem() don't work well in your program as the sidebarmenu requires minor tweaking. Also, you don't need mainPanel. Try this
data_type_list <- c("in vivo","in vitro","pbpk")
ui <- shinydashboard::dashboardPage(title = "ARC Toxkin App", skin = "purple",
shinydashboard::dashboardHeader(
title = "REPORT" ,
tags$li(class = "dropdown",
tags$style(
HTML(
"#import url('//fonts.googleapis.com/css?family=Libre+Baskerville:400,700|Open+Sans:400,700|Montserrat:400,700');"
)
)),
disable = FALSE,
titleWidth = '200'
),
shinydashboard::dashboardSidebar(width = 220,
useShinyjs(),
sidebarMenu(
id = "tabs",
style = "position: relative; overflow: visible;",
menuItem("TK Knowlegebase", tabName="tk", icon = icon("bar-chart-o"),
menuSubItem("TK Knowlegebase1", tabName = "tk1", icon = icon('database')),
selectInput("tk_data_type", label="Select Data Type", choices = data_type_list, selected=1),
menuSubItem("TK Knowlegebase2", tabName = "tk2", icon = icon('database'))
#radioButtons("tk_data_type2", "Select Data Type:",data_type_list)
)
)
),
shinydashboard::dashboardBody( #width = 870,
tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "custom.css"),
),
#theme = shinythemes::shinytheme("darkly"),
tabItems(
#tabItem(tabName = "tk", headerPanel('First')),
tabItem(tabName = "tk1",
fluidRow(
shinydashboard::box(title = "Graphics Package", width = 12, solidHeader = TRUE, status="info",
## vivo
conditionalPanel(
condition = "input.tk_data_type == 'in vivo'",
tags$h2(' vivo')
),
## in vitro
conditionalPanel(
condition = "input.tk_data_type == 'in vitro'",
tags$h2(' vitro')
),
## pbpk
conditionalPanel(
condition = "input.tk_data_type == 'pbpk'",
tags$h2(' pbpk')
),
verbatimTextOutput("tb1"),
DTOutput("tb2")
))
),
tabItem(tabName = "tk2", headerPanel('Last'), DTOutput("tb3")
#verbatimTextOutput("tb4")
)
)
)
)
server <- function(input, output, session) {
output$tb3 <- renderDT(mtcars)
output$tb2 <- renderDT(iris)
output$tb1 <- renderPrint({input$tk_data_type})
output$tb4 <- renderPrint({input$tk_data_type2})
}
shinyApp(ui, server)

Show/Hide entire box content with RadioButton Shiny

I have 3 boxes in the dashboard body. When radioButton in selected to "P3G", box1 and box3 should appear i.e hide box2. When radiobutton is selected to "Chose File", box2 and box3 should appear. I have the below code using shinyjs but it is not working as required i.e. not hiding complete box contents as coded in observeEvent. Any help?
sidebar <- dashboardSidebar(width=200,
sidebarMenu(id="tabs",
menuItem("Input File", tabName =
"tab1",icon = icon("fas fa-file"))))
body <- tabItem(tabName = "tab1",value="file_nput",h2("Select file"),
fluidRow(useShinyjs(),
radioButtons("file_rd",label= "Chose Dataset:",
choices = list("P3G","Chose File"),selected = "P3G"),
box( id ="box1",title = "Default Sample", width = 7, status = "info",
tabPanel("Sample Info",value="p3_samples",
DT::dataTableOutput("p3_table"))),
box(id= "box2", title = "Uploaded Sample", width = 7, status = "info",
tabsetPanel(id = "sam_tab",
tabPanel("Upload", value="upload_file",
fileInput(inputId ="FILE",label = "Upload file",multiple=FALSE,
accept = c(".txt")),
checkboxInput('header', label = 'Header', TRUE),
actionButton("createdb","Create DB")),
tabPanel("File Info",value="samples",tableOutput("summary"),icon = icon("info"),
DT::dataTableOutput("full_table"),actionButton("upload","Proceed")))),
box(id = "box3" ,status = "info", width = 5,
tabBox(id = "infobox", height = "100%", width = "100%",
tabPanel("Instructions",h4("Instructions for uploading valid input file"))))))
ui<- shinyUI(dashboardPage(dashboardHeader(title = "TestApp", titleWidth = 150),sidebar,dashboardBody(tabItems(body))))
server <- function(input, output, session) {
observeEvent(input$file_rd, {
if (input$file_rd == "P3G") {
shinyjs::hide(id = "box2", anim=TRUE)
}else {
shinyjs::hide(id = "box1",anim=TRUE)
}
})
}
shinyApp(ui=ui, server=server)
You can simply use
conditionalPanel()
so conditionalPanel for box1 will be like this:
conditionalPanel('input.file_rd === "P3G"', box(id = 'box1', ...)
and for box2 and box3:
conditionalPanel('input.file_rd != "P3G"', box(id = 'box2', ...), box(id = 'box3', ...)

R Shiny dropdownButton reactive size?

I'm using the dropdownButton from this link that is in Shiny Widgets, with a slight mod to make the text black. drop-down checkbox input in shiny
My goal is to make the dropdownButton in my sidebar look as much like a selectInput feature as possible. I got the button to be the same size as the the selectInput, and the caret to be placed correctly, thanks to help on another post, but when I change the window size, I run into UI overlap issues.
Any suggestions? See my issue below:
Both are screenshots of the same app from the same code, just different window sizes. I'd like the dropdownButton to stay consistent in matching its size to the selectInput above. I also don't understand why my h5("Filter 2:) text splits with the larger window size, and I don't want it to do that.
library(shiny)
library(shinydashboard)
dropdownButton2 <- function(label = "", status = c("default", "primary", "success", "info", "warning", "danger"), ..., width = NULL) {
status <- match.arg(status)
# dropdown button content
html_ul <- list(
class = "dropdown-menu",
style = if (!is.null(width))
paste0("width: ", validateCssUnit(width), ";"),
lapply(X = list(...), FUN = tags$li, style = "margin-left: 10px; margin-right: 10px;color:black")
)
# dropdown button apparence
html_button <- list(
class = paste0("btn btn-", status," dropdown-toggle"),
type = "button",
`data-toggle` = "dropdown"
)
html_button <- c(html_button, list(label))
html_button <- c(html_button, list(tags$span(class = "caret")))
# final result
tags$div(
class = "dropdown",
do.call(tags$button, html_button),
do.call(tags$ul, html_ul),
tags$script(
"$('.dropdown-menu').click(function(e) {
e.stopPropagation();
});")
)
}
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(width = 325,
selectInput('month',label='Filter 1:',choices= month.name,multiple = FALSE,selected = "March"),
br(),
column(1,
h5(strong(("Filter 2:"))),
tags$style(type = 'text/css', ".btn-default{width: 100%;}"),
tags$style(type = 'text/css', ".btn .caret{position: relative;}"),
tags$style(type = 'text/css', ".caret{top: 45%; right:-35%}"),
dropdownButton2(
label = "Filter 2:", status = "default", width = 200,#circle = FALSE,
checkboxGroupInput(inputId = "check1", label = "Choose", choices = c("A","B","C"))
),
h5(strong(("Filter 3:"))),
dropdownButton2(
label = "Filter 3:", status = "default", width = 200,#circle = FALSE,
checkboxGroupInput(inputId = "check3", label = "Choose", choices = c("A","B","C"))
)
)),
dashboardBody()
)
server <- function(input, output){
}
shinyApp(ui = ui, server = server)
#SarahGC - The column you have defined in your code has width = 1 which is being used to display dropdownbuttons. By just changing that value, both your problems will get solved (text wont split on the label, and width of buttons will not be restricted). Please note width must be between 1 and 12.
column(11,
h5(strong("Filter 2:")),
tags$style(type = 'text/css', ".btn-default{width: 100%;}"),
tags$style(type = 'text/css', ".btn .caret{position: relative;}"),
tags$style(type = 'text/css', ".caret{top: 45%; right:-35%}"),
dropdownButton2(
label = "Filter 2:", status = "default",width = 100,#circle = FALSE,
checkboxGroupInput(inputId = "check1", label = "Choose", choices = c("A","B","C"))
),
h5(strong("Filter 3:")),
dropdownButton2(
label = "Filter 3:", status = "default",width = 100,#circle = FALSE,
checkboxGroupInput(inputId = "check3", label = "Choose", choices = c("A","B","C"))
)
)

Resources