All commands in the [shinydashboard](https://rstudio.github.io/shinydashboard/) package, in the same way as the [shiny](http://shiny.rstudio.com/) commands, follow the **camelCase** style. Any shiny dashboard is made up of three main parts: - **header**, with the title, and possibly a *navbar* tabbed menu, and *dropdown* menus for messages, notifications, and tasks - **sidebar**, space normally used for *input controls* - **body**, where the outputs live To launch an empty functional dashboard just run the following template code: ``` library(shinydashboard) header <- dashboardHeader() sidebar <- dashboardSidebar() body <- dashboardBody() ui <- dashboardPage(header, sidebar, body, skin = 'colour_name') server <- function(input, output){} shiny::shinyApp(ui, server) ``` Each part can include any typical shiny object, but also some specific shinydashboard object, as explained below. In the **Header** it's possible to include *drop down* menus: ``` header <- dashboardHeader( dropdownMenu( type = 'messages', messageItem( from = 'author', message = 'message text, href = 'url', icon = icon('icon_name'), # see http://glyphicons.com/ or https://fontawesome.com/ time = 'yyyy-mm-dd' ), messageItem( ... ), ... ), dropdownMenu( type = 'notifications', notificationItem( from = 'author', message = 'notification text', href = 'url' ), notificationItem( ... ), ... ), dropdownMenu( type = 'tasks', taskItem( text = 'task text', value = n # this is the percentage 0-100 of completeness/progress of the task shown as a barchart to the user ), taskItem( ... ), ... ) ) ``` The above menus have been filled manually, which doesn't look ideal. It's obviously possible to add items automatically and dynamically, iterating over a preloaded or timely polled dataframe or list. As always in Shiny, there needs to be a placeholder for the output in the ui part of the app, called `dropdownMenuOutput`, and a correspondent render function in the server part, called `renderMenu`, that generates the actual output. There are many ways to generate the list of items to feed the `dropdownMenu` function. The following, regarding *messages*, is only an example that assumes that the content for the messages come from a dataframe called *msg_df* which has at least three columns: *from*, *message*, *time*. ``` # UI dashboardHeader( dropdownMenuOutput('msg_menu') ) # SERVER output$msg_menu <- renderMenu({ msg_lst <- apply(msg_df, 1, function(x) messageItem(from = x[['from']], message = x[['message']], time = x[['time']]) ) dropdownMenu(type = "messages", .list = msg_lst) }) ``` In the **sidebar** it's possible to include row *tabs* that are connected to tabbed page(s) in the body: ``` sidebar <- dashboardSidebar( sidebarMenu( menuItem('first_title', tabName = 'first_tab_id' # this is the lookup item for the tab in the body ), menuItem('second_name', tabName = 'second_tab_id' ), ... ) ) ``` In the **body** it's possible to include many sorts of objects, like *tabs* (that can be connected with the sidebar by the `tabName`) ``` dashboardBody( tabBox( title = "first level box title text", tabPanel("first_level_first_tab_id", "Content for the first tab"), tabPanel("first_level_second_tab_id", "Content for the second tab") ), tabItems( tabItem( tabName = 'first_tab_id', tabBox( title = "second level box title text", tabPanel("second_level_first_tab_id", "Content for the first tab"), tabPanel("second_level_second_tab_id", "Content for the second tab") ), ), tabItem( tabName = 'second_tab_id', ... ), ... ) ) ``` A **box** is a peculiar object of a shinydashboard, and represent a rectangular portion of the body of possibly fixed width and height, using the `width` argument. It can assume one of the four following forms: - box ``` ``` - infoBox ``` infoBox( width = n, title = "title text", subtitle = "subtitle text", icon = icon('icon_name'), status = 'colour_name', colour = 'colour_name' ) ``` - valueBox ``` ``` - tabBox ``` ``` It might be useful to know that some valid statuses and their corresponding colors for the boxes are: - **primary** *Blue* - **success** *Green* - **info** *Blue* - **warning** *Orange* - **danger** *Red* It is possible to create reactive boxes in the usual Shiny way: - the reactive functions `renderValueBox` in the server to generate the object, - the corresponding ui functions `valueBoxOutput` that create the placeholder. ``` # UI dashboardBody( valueBoxOutput('box_id') ) # SERVER output$box_id <- renderValueBox({ valueBox( value = input$click, subtitle = 'Click Box', ) }) ``` One characteristic of a dashboard is the ability to examine and present *real-time* data. In shiny, this can be done using one of the following functions, depending on the input: ``` reactiveFileReader( intervalMillis = n, session = session, filePath = path, readFunc = fun # the function used to read the data, it can also be user defined ) ``` ``` reactivePoll( ) ``` --- Shiny is built over the [Bootstrap](https://getbootstrap.com/) framework, that follows a strict grid layout that spread along 12 columns width. There are only two possible ways of distributing content: - column-based ``` fluidRow( column(width = 6, box( width = NULL, # with column layouts, this is mandatory title = 'box on the left', subtitle = '?' ), box( width = NULL, title = 'box on the right', subtitle = '?' ) ) ) ``` - row-based: ``` fluidRow( box( width = 6, title = 'upper box', subtitle = '?' ), box( width = 6, title = 'lower box', subtitle = '?' ) ) ``` In addition to the above layouts, it's also possible to have a mixed layouts that combine the two. --- To enhancing the style of the dashboard it's possible to change any attribute of the page using a file with css commands, and then importing the file when calling the `dashboardPage` function: ``` dashboardPage( header, sidebar, body, skin = 'colour_name', tags$head( tags$link( rel = 'stylesheet', type = 'text/css', href = '/path/to/filename.css' ) ) ) ``` --- Icons are a great way to make a dashboard look more polished! icons can be rendered in shiny using the icon() function that require at least the name of the icon, as it's listed at [font-awesome](https://fontawesome.com/) or [glyphicons](http://glyphicons.com/), and the name of library, if different from *font awesome*. It's also possible to add a value to the `class` argument to get a different sub-style: ``` icon('', class = '') icon('', , class = '') ``````