Search code examples
rshinyshinydashboard

R Shiny renderTable - how to change borders width and color


I probably have a simple question but since I'm not very familiar with CSS/htlm I'm having a hard time to figure out the following problem. In my ui I have the following simple table:

tableOutput("retail_dashboard_ratios_table")

in the server, I have this very simple code:

output$retail_dashboard_ratios_table <- renderTable({  #
df <- head(mtcars)
})

All I would need to do is to set the borders width and borders color (to blue). I'm obliged to use the R 3.4 version. Since I have a static tableOutput, I cannot (apparently) use solution mentioned in Add Cell Borders in an R Datatable because I cannot return a datatable object.

I also read R shiny renderTable change cell colors that has a very interesting solution, but given my R version, it seems library(tableHTML) is not compatible.

I wonder if anybody has a simple solution simply to fix the borders. Thanks


Thanks to @Patrick Altmeyer this is the final working solution!

source("global.R") 

today <- as.character()

ui <- dashboardPage(  
  title = "Dashboard of the Municipal Market",  # this is the name of the tab in Chrome browserr
  dashboardHeader(title = "Web Portal"),

  dashboardSidebar(   
    sidebarMenu(

      menuItem('Retail', tabName = "retail", icon = icon("th"),
               menuItem('Dashboard', tabName = 'retail_dashboard'))
    )
  ),

  dashboardBody( 
      tabItem(tabName = "retail_dashboard",
              tabsetPanel(type = "tabs",
                          tabPanel("Dashboard",
                                   h3("Test."),

                                   tags$head(
                     tags$style(HTML("
                                                .my_table_aa01 .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
                                                border-collapse: collapse;
                                                }

                                                .my_table_aa01 th {
                                                 border: 1px solid black !important;
                                                 text-align: center !important;
                                                 vertical-align: middle !important;
                                                 color: white !important;
                                                 background-color: #615858 !important;
                                                 white-space: nowrap;
                                                 border-bottom: none}

                                                .my_table_aa01 td {padding: 1rem;
                                                border: 1px solid black;}

                                                .my_table_aa01 tr:first-child {
                                                  border : 1px solid black;
                                                 border-top: 1px solid black;}

                                                 .my_table_aa01 tr:nth-child(even){
                                                 background-color: #afd19d;
                                                 color: black;
                                                 font-size:16px;}

                                                 .my_table_aa01 tr:nth-child(odd){
                                                 background-color: white;
                                                 color: black;
                                                 font-size:16px;
                                                 }
                                                "))),

                                   fluidRow(column(2,
                                                   actionButton(inputId = "retail_dashboard_load_data_btn", label = "Load / Refresh Data")),
                                            column(2,
                                                   downloadButton("download_dashboard_data","Download Data"))),

                                   fluidRow(
                                     column(2, 
                                            dateInput("retail_dashboard_start_dt", label = ("Start Date"), value = glob_date_1yr_ago)),
                                     column(2, 
                                            dateInput("retail_dashboard_end_dt", label = ("End Date"), value = glob_previous_to_most_recent_date_with_quant_model_regression_data))
                                   ),


                                   br(),
                                   fluidRow(column(6,
                                                   div(textOutput(outputId = "retail_dashboard_error_log")))),
                                   br(),

                                   fluidRow(column(3,
                                                   plotlyOutput(outputId = "retail_dashboard_plot1", width = '350', height = '350px')),
                                            column(3,
                                                   offset = 0,
                                                   tags$div(
                                                     class="my_table_aa01", # set to custom class
                                                     tableOutput("retail_dashboard_ratios_table") )


                                            )),
                                   fluidRow(column(3,
                                                   tableOutput("retail_dashboard_table2")))
                                     )
                                     )             
              )
              )
)


server <- function(input, output, session) {    
  source("Page_retail_dash.R", local=T) 


}

cat("\nLaunching   'shinyApp' ....")
shinyApp(ui, server)

Solution

  • A more elegant solution would probably work with a style sheet, but if it's just one table you are trying to style you could simply add CSS to the HTML header as below. More info on this can be found here. I find that the tricky part is often to know what class to overwrite as in this case .table>tbody>tr>td, .... But a simple way to find what you're looking for is to inspect the HTML at runtime, e.g. in Google Chrome you would right-click + "Inspect" anywhere in the browser window (preferably close to the element you want to style). You can then edit the style in the browser at runtime to preview how your changes to the CSS would affect the appearance off your app. I'm not very familiar with CSS either, but this is approach usually gets me a long way.

    Hope this helps!

    shinyApp(
    
      # --- User Interface --- #
    
      ui = fluidPage(
    
        # The below overwrites the default styling for the top border of table cells. 
        # I've changed the colour to blue from grey and the width to 3px from 1px.
        tags$head(
          tags$style(HTML("
          .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
            padding: 8px;
            line-height: 1.42857143;
            vertical-align: top;
            border-top: 3px solid blue; 
          }
        "))
        ),
    
        mainPanel(
          tableOutput("retail_dashboard_ratios_table")
        )
    
      ),
    
      # --- Server logic --- #
    
      server = function(input, output) {
        output$retail_dashboard_ratios_table <- renderTable({  #
          df <- head(mtcars)
        })
      }
    
    )
    

    Edit

    In case you want to set the style for one table only, rather than all tables in you app, you need to create your own CSS class for it. You can provide a name four class rather easily by simply writing e.g .my_table or #my_table in front of the existing CSS code above. So to complete the above example, but now with individual styling:

    shinyApp(
    
      # --- User Interface --- #
    
      ui = fluidPage(
    
        # The below now creates a custum css class. 
        tags$head(
          tags$style(HTML("
          .my_table .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
            padding: 8px;
            line-height: 1.42857143;
            vertical-align: top;
            border-top: 3px solid blue; 
          }
        "))
        ),
    
        mainPanel(
          h3("Custom style table:"),
          tags$div(
            class="my_table", # set to custom class
            tableOutput("custom_table")
          ),
          h3("Default style table:"),
          tableOutput("default_table"), # No class assigned
          h3("Another default style table:"),
          tableOutput("another_default_table") # No class assigned
        )
    
      ),
    
      # --- Server logic --- #
    
      server = function(input, output) {
        output$custom_table <- renderTable({  #
          df <- head(mtcars)
        })
    
        output$default_table <- renderTable({  #
          df <- head(iris)
        })
    
        output$another_default_table <- renderTable({  #
          df <- head(cars)
        })
      }
    
    )
    

    Below is the output the code produces: enter image description here