Can I have some guidance please in how to update the descriptionBlock in a shiny app with a bs4Dash dashboard? Thanks in advance.
I have tried multiple approaches but can’t seem to get the descriptionBlock values to change on the server and send to the UI; some have resulted in strange width behaviour and for that reason I have included a placeholder box to the left of width 9, beside my target box (width = 3) to the right.
It would seem that there should be an easy server side way to update these values and send to the UI but I just can’t find it. To keep it simple… I am looking to update on an event (actionButton click).
library(shiny)
library(bs4Dash)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(),
dashboardBody(
fluidRow(
column(12, actionButton('btn_update', 'UPDATE right box'))
),
br(),
fluidRow(
box(
title = textOutput("box_state"),
"Box body",
id = "mybox1",
collapsible = F,
closable = F,
width = 9
),
box(
title = textOutput("box_state"),
id = "mybox2",
collapsible = F,
closable = F,
width = 3,
descriptionBlock(
number = '100',
numberColor = 'success',
numberIcon = icon("caret-up"),
header = NULL,
text = 'stuff',
rightBorder = TRUE,
marginBottom = FALSE
)
)
)
)
)
server <- function(input, output) {
observeEvent(input$btn_update,{
# How is this sent as an update to the UI please?
descriptionBlock(
number = '-999',
numberColor = 'danger',
numberIcon = icon("caret-down"),
header = NULL,
text = 'different stuff',
rightBorder = TRUE,
marginBottom = FALSE
)
})
}
shinyApp(ui, server)
I am trying to add a navlistPanel to a box() in bs4Dash and when I set the column width to 12, the tabItems squeeze next to each other like this:
Adding the widths = c(4,8) argument to navlistPanel also gives me the same result. If I set the column width to 4 or less, the navlistPanel is properly formatted.
My goal is to have a box() with column = 12 and a vertical tab menu inside it with width = 4 and have the tabs look correct.
I've also tried using tabsetPanel with vertical = TRUE, but the content doesn't show up in the right location, it shows up below. See picture #2:
Reprexes for both are below:
library(shiny)
library(bs4Dash)
ui <- dashboardPage(
header = dashboardHeader(
title = dashboardBrand(
title = "My dashboard",
color = "primary",
href = "https://adminlte.io/themes/v3",
image = "https://adminlte.io/themes/v3/dist/img/AdminLTELogo.png"
)),
sidebar = bs4DashSidebar(),
controlbar = dashboardControlbar(),
body = dashboardBody(fluidRow(column(
12,
box(
title = "Title",
status = "primary",
solidHeader = TRUE,
collapsible = FALSE,
maximizable = TRUE,
color = "white",
height = 175,
width = NULL,
navlistPanel(
"Header",
tabPanel("First"),
tabPanel("Second"),
tabPanel("Third")
)
)
))),
help = FALSE,
dark = NULL,
scrollToTop = FALSE
)
server = function(input, output, session) {
}
shinyApp(ui, server)
library(shiny)
library(bs4Dash)
ui <- dashboardPage(
header = dashboardHeader(
title = dashboardBrand(
title = "My dashboard",
color = "primary",
href = "https://adminlte.io/themes/v3",
image = "https://adminlte.io/themes/v3/dist/img/AdminLTELogo.png"
)),
sidebar = bs4DashSidebar(),
controlbar = dashboardControlbar(),
body = dashboardBody(fluidRow(column(
12,
box(
title = "Title",
status = "primary",
solidHeader = TRUE,
collapsible = FALSE,
maximizable = TRUE,
color = "white",
height = 175,
width = NULL,
tabsetPanel(
id = NULL,
vertical = TRUE,
tabPanel("First",
"The content is below and I want it to the right of the tabset"),
tabPanel("Second"),
tabPanel("Third")
)
)
))),
help = FALSE,
dark = NULL,
scrollToTop = FALSE
)
server = function(input, output, session) {
}
shinyApp(ui, server)
Using bs4Dash, I am trying to create a box that contains several other boxes, have them horizontally aligned, and span equal-distances across the page no matter how big or small the window is. I was able to get the boxes in-line using a div(), but cannot seem to make them equidistant in width.
This is my reproducible example:
if (interactive()) {
library(shiny)
library(bs4Dash)
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(width = 12, div(style="display: inline-block;vertical-align:top;", box(
solidHeader = FALSE,
title = "Status summary",
background = NULL,
width = 12,
status = "danger",
footer = fluidRow(
descriptionBlock(
number = "17%",
numberColor = "pink",
numberIcon = icon("caret-up"),
header = "$35,210.43",
text = "TOTAL REVENUE",
rightBorder = TRUE,
marginBottom = FALSE
),
descriptionBlock(
number = "18%",
numberColor = "secondary",
numberIcon = icon("caret-down"),
header = "1200",
text = "GOAL COMPLETION",
rightBorder = FALSE,
marginBottom = FALSE
)
)
)),
div(style="display: inline-block;vertical-align:top;", box(title = "second box", width = 12))
)
)
),
title = "Description Blocks"
),
server = function(input, output) { }
)
}
I'm not sure if you've answered this question since you posted it, but it might be useful for others.
In bs4Dash, the key is to use constant combinations of fluidRow(column(width = X, box(width = NULL))) even within boxes.
For example, a box with two boxes inside of it might look like this:
column(width = 12,
box(width = NULL, title = "Main box",
fluidRow(
column(width = 6,
box(width = NULL, title = "Internal box 1")
),
column(width = 6,
box(width = NULL, title = "Internal box 2")
)
)
)
)
Here's a reproducible example that should achieve your outcomes:
library(shiny)
library(bs4Dash)
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
fluidRow(
column(width = 12,
box(width = NULL,
fluidRow(
column(width = 6,
box(
solidHeader = FALSE,
title = "Status summary",
background = NULL,
width = NULL,
status = "danger",
footer = fluidRow(
column(width = 6,
descriptionBlock(
number = "17%",
numberColor = "pink",
numberIcon = icon("caret-up"),
header = "$35,210.43",
text = "TOTAL REVENUE",
rightBorder = TRUE,
marginBottom = FALSE
)
),
column(width = 6,
descriptionBlock(
number = "18%",
numberColor = "secondary",
numberIcon = icon("caret-down"),
header = "1200",
text = "GOAL COMPLETION",
rightBorder = FALSE,
marginBottom = FALSE
)
)
)
)
),
column(width = 6,
box(title = "second box", width = NULL))
)
)
)
)
)
)
server = function(input, output) { }
shinyApp(ui = ui, server = server)
I have a shiny app that looks like this:
I would like to add a Box 3 and Box 4 beneath the mouse logo, but cannot seem to figure out how to do this without messing the page up. The result is below:
i am using two fluidRow functions to make these boxes, but I am not sure how I can keep the entire page intact while doing so. Any help is appreciated! Code is below:
#require packages
rqrd_Pkg = c('shiny','plotly','plyr','tidyverse',
'uuid', 'devtools', 'gtools', 'inline', 'shiny',
'shinydashboard', 'plotly', 'shinythemes',
'shinycssloaders', 'shinyjs',
'DT', 'tictoc',
'data.table', 'htmlwidgets')
require(shiny)
for(p in rqrd_Pkg){
if(!require(p,character.only = TRUE))
install.packages(p, Ncpus=8);
library(p,character.only = TRUE)
}
#include style for header
head.style <- "
/* old shiny progress indicators */
.shiny-progress-container {
position: fixed;
top: 0px;
width: 100%;
z-index: 4000;
}
.shiny-progress .progress-text {
color: #020202;
background-colort: #FF0000;
width: 225px;
left: calc(50% - 125px);
}
.progress-text {
/* Copy the below to vertically center the progress bar text box in the shiny dashboard header */
/* !important is crucial here otherwise it gets overridden by the dreaded element.style */
top: 15px !important;
text-align: center;
}
"
#initiate dashboard attributes and colors
dashboardPage(
skin = "purple",
dashboardHeader(
title = HTML("Title"),
dropdownMenu(type = "notifications", icon = tagList(icon("question-circle"), "Help"), badgeStatus = NULL, headerText = "Links",
tags$li(a(icon("external-link"), "XYZ", href = "http://info.com", target = "blank")),
tags$li(a(icon("external-link"), "ABC", href = "http://info.com", target = "blank")))
),
dashboardSidebar(sidebarMenu(
menuItem("Target Dashboard", tabName = "dashboard_tab", icon = icon("dashboard"))
)),
#################################################################################
#################################################################################
#################################################################################
#################################################################################
#Configure dashboard body.
dashboardBody(
tags$head(
tags$link(rel = "shortcut icon", href = "favicon.ico"),
tags$link(rel = "apple-touch-icon", sizes = "180x180", href = "favicon.ico"),
tags$link(rel = "icon", type = "image/png", sizes = "32x32", href = "favicon-32x32.png"),
tags$link(rel = "icon", type = "image/png", sizes = "16x16", href = "favicon-16x16.png"),
tags$style(head.style)
),
#h1(paste0("<b>","Gene summary:","</b>")),
titlePanel(div(HTML("<b>Gene summary</b>"), align = "left")),
tabItems(
tabItem(tabName = "dashboard_tab",
tags$style(HTML("
#first {
border: 4px double red;
}
#second {
border: 2px dashed blue;
}
")),
fluidRow(
valueBoxOutput("valueGeneName"),
valueBoxOutput("valueGeneRank"),
valueBoxOutput("gtexSpec"),
valueBoxOutput("valueHuman"),
valueBoxOutput("valueMouse"),
valueBoxOutput("valueNHP"),
valueBoxOutput("exprCompartment")
),
h2(paste0("Header 1"), align="left"),
#insert human logo
mainPanel(
img(src='man_log.png', height="10%", width="10%", align="left"),
),
#create boxes
fluidRow(
box(
title = "Box 1",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("roc", height = "300px")
),
box(
title = "Box 2"
,status = "primary"
,solidHeader = TRUE
,collapsible = TRUE
,plotOutput("sensDNAProt", height = "300px")
)),
mainPanel(
img(src='mouse.png', height="10%", width="10%", align="left")
),
h2(paste0("Header 2"), align="left"),
#ADDING THIS CAUSES PROBLEMS!!!
fluidRow(
box(
title = "Box 3",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("roc", height = "300px")
),
box(
title = "Box 4",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("roc", height = "300px")
)
)
)
)
)
)
`
You should get the desired output with this.
### include style for header
head.style <- "
/* old shiny progress indicators */
.shiny-progress-container {
position: fixed;
top: 0px;
width: 100%;
z-index: 4000;
}
.shiny-progress .progress-text {
color: #020202;
background-colort: #FF0000;
width: 225px;
left: calc(50% - 125px);
}
.progress-text {
/* Copy the below to vertically center the progress bar text box in the shiny dashboard header */
/* !important is crucial here otherwise it gets overridden by the dreaded element.style */
top: 15px !important;
text-align: center;
}
"
#initiate dashboard attributes and colors
ui <- dashboardPage(
skin = "purple",
dashboardHeader(
title = HTML("Title"),
dropdownMenu(type = "notifications", icon = tagList(icon("question-circle"), "Help"), badgeStatus = NULL, headerText = "Links",
tags$li(a(icon("external-link"), "XYZ", href = "http://info.com", target = "blank")),
tags$li(a(icon("external-link"), "ABC", href = "http://info.com", target = "blank")))
),
dashboardSidebar(sidebarMenu(
menuItem("Target Dashboard", tabName = "dashboard_tab", icon = icon("dashboard"))
)),
#################################################################################
#################################################################################
#################################################################################
#################################################################################
#Configure dashboard body.
dashboardBody(
tags$head(
tags$link(rel = "shortcut icon", href = "favicon.ico"),
tags$link(rel = "apple-touch-icon", sizes = "180x180", href = "favicon.ico"),
tags$link(rel = "icon", type = "image/png", sizes = "32x32", href = "favicon-32x32.png"),
tags$link(rel = "icon", type = "image/png", sizes = "16x16", href = "favicon-16x16.png"),
tags$style(head.style)
),
#h1(paste0("<b>","Gene summary:","</b>")),
titlePanel(div(HTML("<b>Gene summary</b>"), align = "left")),
tabItems(
tabItem(tabName = "dashboard_tab",
tags$style(HTML("
#first {
border: 4px double red;
}
#second {
border: 2px dashed blue;
}
")),
fluidRow(width=12,
tabBox(id = "tabset1", height = "2250px", width=12, title = " ",
tabPanel(
br(),br(),
fluidRow(h2(paste0("Header 0"), align="left")),
fluidRow(
shinydashboard::valueBoxOutput("myvaluebox1", width=4),
shinydashboard::valueBoxOutput("myvaluebox2", width=4),
shinydashboard::valueBoxOutput("myvaluebox3", width=4)
),
fluidRow(
shinydashboard::valueBoxOutput("myvaluebox4", width=4),
shinydashboard::valueBoxOutput("myvaluebox5", width=4),
shinydashboard::valueBoxOutput("myvaluebox6", width=4)
),
fluidRow(
shinydashboard::infoBoxOutput("myvaluebox7", width=4),
shinydashboard::valueBoxOutput("myvaluebox8", width=4)
),
br(),
fluidRow(h2(paste0("Header 1"), align="left")),
#br(),
fluidRow(img(src='man_log.png', height="5%", width="5%", align="left")),
br(),
fluidRow(
column(6,
box( height="300px", width=NULL,
collapsible = TRUE,
title = "Box 1",
status = "primary",
solidHeader = TRUE,
plotOutput("plot1", height = "210px", width="350px")
), style='width: 500px; height: 400px' ),
column(6,
box(height="300px", width="450px",
title = "Box 2",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("plot2", height = "230px", width="380px")
), style='width: 500px; height: 400px')
),
br(),# br(),
img(src='mouse.png', height="10%", width="10%", align="left"),
br(),
h2(paste0("Header 2"), align="left"),
br(),
fluidRow(
column(6,
box(height="300px", width="450px",
title = "Box 3",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("plot3", height = "220px", width="350px")
), style='width: 500px; height: 400px' ),
column(6,
box(height="300px", width="450px",
title = "Box 4",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
plotOutput("plot4", height = "220px", width="350px")
), style='width: 500px; height: 400px')
)
) ## end of tabPanel
) ## end of tabBox
)
) ## end of tabItem
)
)
)
server <- function(input, output, session){
output$plot1 <- renderPlot(qplot(rnorm(500),fill=I("red"),binwidth=0.2,title="plotgraph1"))
output$plot2 <- renderPlot(qplot(rnorm(500),fill=I("green"),binwidth=0.2,title="plotgraph2"))
output$plot3 <- renderPlot(qplot(rnorm(500),fill=I("blue"),binwidth=0.2,title="plotgraph3"))
output$plot4 <- renderPlot(qplot(rnorm(500),fill=I("orange"),binwidth=0.2,title="plotgraph4"))
output$myvaluebox1 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2000',subtitle = "blah blah blah1",icon = icon("car"),
color = "green"
)
})
output$myvaluebox2 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2001',subtitle = "blah blah blah2",icon = icon("car"),
color = "green"
)
})
output$myvaluebox3 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2002',subtitle = "blah blah blah3",icon = icon("car"),
color = "green"
)
})
output$myvaluebox4 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2009',subtitle = "blah blah blah4",icon = icon("car"),
color = "red"
)
})
output$myvaluebox5 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2010',subtitle = "XYZ1",icon = icon("car"),
color = "red"
)
})
output$myvaluebox6 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2011',subtitle = "XYZ2",icon = icon("car"),
color = "green"
)
})
output$myvaluebox7 <- shinydashboard::renderInfoBox({
shinydashboard::infoBox('2020',subtitle = "This is infobox",icon = icon("car"),
color = "blue"
)
})
output$myvaluebox8 <- shinydashboard::renderValueBox({
shinydashboard::valueBox('2021',subtitle = "This is valuebox",icon = icon("car"),
color = "blue"
)
})
}
shinyApp(ui = ui, server = server)
I've created a circle with CSS that should contain a number in the middle, with the help of this SO answer
# Packages
library(shinydashboard)
library(tidyverse)
library(readxl)
library(scales)
theme_set(theme_light())
header <- dashboardHeader(
title = "Test App",
titleWidth = 215
)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Test Tab", tabName = "test_tab",
icon = icon("paper-plane"), startExpanded = TRUE)
)
)
body <- dashboardBody(
includeCSS("www/style.css"),
tabItems(
tabItem(tabName = "test_tab",
fluidRow(
column(width = 4,
h2("Column X"),
valueBoxOutput("first_value", width = NULL),
box(flexdashboard::gaugeOutput("second_value", width = "90%", height = "100px"),
title = "Second Value", status = "primary", solidHeader = TRUE,
collapsible = FALSE, width = NULL
)
),
column(width = 8,
h2("Column Y"),
box(tags$div(id="insidediv", textOutput("test_div")),
title = "#3", status = "primary", solidHeader = TRUE,
collapsible = FALSE, width = 4
),
box(
title = "#4", status = "primary", solidHeader = TRUE,
collapsible = FALSE, width = 4
)
)
),
fluidRow(
h2("Row A"),
column(width = 12,
box(title = "Third Value", status = "primary", solidHeader = TRUE,
width = 2.4),
box("Fourth Value", status = "primary", solidHeader = TRUE,
width = 2.4),
box("Fifth Value", status = "primary", solidHeader = TRUE,
width = 2.4),
box("Sixth Value", status = "primary", solidHeader = TRUE,
width = 2.4),
box("Seventh Value", status = "primary", solidHeader = TRUE,
width = 2.4)
)
)
)
)
)
# Put them together into a dashboardPage
ui <- dashboardPage(skin = "blue", header = header,
sidebar = sidebar,
body = body)
server <- function(input, output) {
output$first_value <- renderValueBox({
valueBox(
comma_format()(100000),
subtitle = "First Value",
icon = icon("list"), color = "purple"
)
})
output$second_value = flexdashboard::renderGauge({
flexdashboard::gauge(0.12 * 100,
symbol = '%',
min = 0,
max = 100)
})
output$test_div <- renderText({
"141"
})
}
shinyApp(ui, server)
Unfortunately, the number doesn't appear inside the circle, but outside it... Does anyone know what the problem may be???
The linked SO answer seems to have it right, but under different circumstances... maybe since I'm putting it inside a box(), its different?
If you are not familiar with it:
The CSS # Selector is for giving ONE specific HTML Element a specific look. Shiny gives textOutput an ID which is test_div in your example. You also have to use that ID in your CSS to style the element.
#test_div {
padding-top: 30px;
padding-bottom: 30px;
text-align: center;
font-weight: bold;
font-size: 24px;
}
I had to play around with the padding, which defines the space around the elements content. Instead of pixels you can also use % (padding: 5%)
https://www.w3schools.com/css/css_padding.asp
Learning the basics of CSS is quite easy and will improve your abitilies to make look shiny a lot :-).