box()
is without any doubt a central component of
{shinydashboard}
. Thanks to the AdminLTE API,
{shinydashboardPlus}
is able to provide more interactivity
to this component. For instance, you may:
To benefit from that feature, one must pass the id parameter
and access it on the server side with input$<id>
.
Let’s consider an example.
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
ui <- dashboardPage(
title = "Box API",
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
tags$style("body { background-color: ghostwhite}"),
fluidRow(
actionButton("toggle_box", "Toggle Box"),
actionButton("remove_box", "Remove Box", class = "bg-danger"),
actionButton("restore_box", "Restore Box", class = "bg-success"),
actionButton("update_box", "Update Box", class = "bg-primary")
),
br(),
box(
title = textOutput("box_state"),
"Box body",
id = "mybox",
collapsible = TRUE,
closable = TRUE,
plotOutput("plot")
)
)
)
server <- function(input, output, session) {
output$plot <- renderPlot({
req(!input$mybox$collapsed)
plot(rnorm(200))
})
output$box_state <- renderText({
state <- if (input$mybox$collapsed) "collapsed" else "uncollapsed"
paste("My box is", state)
})
observeEvent(input$toggle_box, {
updateBox("mybox", action = "toggle")
})
observeEvent(input$remove_box, {
updateBox("mybox", action = "remove")
})
observeEvent(input$restore_box, {
updateBox("mybox", action = "restore")
})
observeEvent(input$update_box, {
updateBox(
"mybox",
action = "update",
options = list(
title = h2("New title", dashboardLabel(1, status = "primary")),
status = "danger",
solidHeader = TRUE,
width = 4
)
)
})
observeEvent(input$mybox$visible, {
collapsed <- if (input$mybox$collapsed) "collapsed" else "uncollapsed"
visible <- if (input$mybox$visible) "visible" else "hidden"
message <- paste("My box is", collapsed, "and", visible)
showNotification(message, type = "warning", duration = 1)
})
}
shinyApp(ui, server)
We call the updateBox()
function, specifying the action
to accomplish:
Knowing the state of a box significantly opens new possibilities within the application, thereby increasing interactivity. Additionally, the toggle animation has been speed up (from 0.5s to 0.1s) so as to reduce the latency.
If you want to know more about the underlying mechanisms, have a look at the box widget documentation.
With {shinydashboardPlus}
, you may embed labels, a
sidebar and dropdown menus in the box header.
boxLabel()
are passed in the box()
label slot. They typically contain number or a short text.
boxDropdown()
is a super powerful tool since all
dropdown items may behave like action buttons. This feature allows to
seamlessly add interactivity to the box component and gather features in
one place. In the example below, clicking on the first item triggers a
Shiny notification.
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
box(
title = "Closable Box with dropdown",
closable = TRUE,
width = 12,
status = "warning",
solidHeader = FALSE,
collapsible = TRUE,
dropdownMenu = boxDropdown(
boxDropdownItem("Click me", id = "dropdownItem", icon = icon("heart")),
boxDropdownItem("item 2", href = "https://www.google.com/"),
dropdownDivider(),
boxDropdownItem("item 3", icon = icon("th"))
),
"My box"
)
)
),
server = function(input, output) {
observeEvent(input$dropdownItem, {
showNotification("Hello", duration = 1, type = "message")
})
}
)
{shinydashboardPlus}
provides more box components to be
able to adapt to various situations. What if you wanted to create a box
with comments, with social content?
userBox()
is intended to highlight user profiles. It has
many common parameters with box()
and overall the same
layout. The 2 major differences between box()
and
userBox()
are:
Additionally, you may also select 2 types: centered image or left-aligned image.
The title argument expects a
userDescription()
:
userDescription(
title = "Nadia Carmichael",
subtitle = "lead Developer",
type = 2,
image = "https://adminlte.io/themes/AdminLTE/dist/img/user7-128x128.jpg",
)
You may also select 2 types: centered image or left-aligned image, as shown in the Figure below.
userBox()
plays well with other components like
navPills()
, as shown below.
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
userBox(
title = userDescription(
title = "Nadia Carmichael",
subtitle = "lead Developer",
type = 2,
image = "https://adminlte.io/themes/AdminLTE/dist/img/user7-128x128.jpg",
),
status = "warning",
navPills(
id = "pillItem",
navPillsItem(
left = "Item 1",
color = "green",
right = 10
),
navPillsItem(
left = "Item 2",
color = "red",
icon = icon("angle-down"),
right = "10%"
)
),
footer = "The footer here!"
)
),
title = "userBox"
),
server = function(input, output) {
observeEvent(input$pillItem, {
if (input$pillItem == 2) {
showModal(
modalDialog("A modal")
)
}
})
observeEvent(input$pillItem, {
showNotification(
sprintf("You clicked on pill N° %s", input$pillItem),
type = "warning",
duration = 1
)
})
}
)
userBox()
is also entirely updatable from the server
side, as it is built on top the box()
function:
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
actionButton("update_box", "Update"),
userBox(
id = "userbox",
title = userDescription(
title = "Nadia Carmichael",
subtitle = "lead Developer",
type = 2,
image = "https://adminlte.io/themes/AdminLTE/dist/img/user7-128x128.jpg",
),
status = "primary",
gradient = TRUE,
background = "light-blue",
boxToolSize = "xl",
"Some text here!",
footer = "The footer here!"
)
),
title = "userBox"
),
server = function(input, output) {
observeEvent(input$update_box, {
updateBox(
"userbox",
action = "update",
options = list(
title = userDescription(
title = "Jean Box",
subtitle = "Developer",
type = 1,
image = "https://adminlte.io/themes/AdminLTE/dist/img/user3-128x128.jpg",
),
status = "red",
background = NULL,
width = 4
)
)
})
}
)
The flipBox()
is a simple container based on the W3C
documentation. It is not originally part of AdminLTE but deserves a
place in {shinydashboardPlus}
. It has a front and back
container, which may help to display extra information. Be sure to
provide the id so that the box may flip. On the server side, a
flipBox
is toggled by updateFlipBox
. There are
currently 2 events, that is click and hover.
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
fluidRow(
column(
width = 6,
uiOutput("active_side"),
actionButton("toggle", "Toggle flip box"),
flipBox(
id = "myflipbox",
trigger = "hover",
width = 12,
front = div(
class = "text-center",
h1("Flip on hover"),
img(src = "https://placehold.co/600x400")
),
back = div(
class = "text-center",
height = "300px",
width = "100%",
h1("Flip on hover"),
p("More information....")
)
)
),
column(
width = 6,
uiOutput("active_side_2"),
flipBox(
id = "myflipbox2",
width = 12,
front = div(
class = "text-center",
h1("Flip on click"),
img(src = "https://placehold.co/600x400")
),
back = div(
class = "text-center",
height = "300px",
width = "100%",
h1("Flip on click"),
p("More information....")
)
)
)
)
)
),
server = function(input, output, session) {
output$active_side <- renderUI({
side <- if (input$myflipbox) "front" else "back"
dashboardBadge(side, color = "blue")
})
output$active_side_2 <- renderUI({
side <- if (input$myflipbox2) "front" else "back"
dashboardBadge(side, color = "blue")
})
observeEvent(input$toggle, {
updateFlipBox("myflipbox")
})
}
)
socialBox
A
socialBox()
is dedicated to contain events, comments, anything related to people. The title parameter hostsuserBlock()
:Elements like
attachmentBlock()
anduserMessages()
are a good fit with this component. The...
slot may hosts multipleboxComment
, consisting in user comments. Right now, there is no programmatic way (understand no update function is available) to handle them but a future release of{shinydashboardPlus}
will obviously fill this gap. The app below shows a combination of multiple elements in asocialBox()
, as well as theupdateBox()
feature:Code