7

I want to add a vertical line between groups of columns. Here is a desired outcome:

---------
g1  | g2
---------
a b | a b
---------
1 2 | 3 4
---------

and a shiny app to start with:

library(shiny)
library(DT)
library(htmltools)

runApp(shinyApp(
  ui <- basicPage(
    DT::dataTableOutput('table1')
  ),
  server = function(input, output) {
    output$table1 <- DT::renderDataTable({
      datatable(data.frame(a1 = 1, b1 = 2, a2 = 3, b2 = 4), rownames = FALSE,
                container = withTags(table(
                  class = 'display',
                  thead(
                    tr(
                      th(colspan = 2, 'g1'),
                      th(colspan = 2, 'g2')
                    ),
                    tr(
                      lapply(rep(c('a', 'b'), 2), th)
                    )
                  )
                ))
      )
    })
  }
))

Current output from shiny app above:

enter image description here

zx8754
  • 52,746
  • 12
  • 114
  • 209
danas.zuokas
  • 4,551
  • 4
  • 29
  • 39
  • Might help: https://datatables.net/examples/advanced_init/row_grouping.html – Mikael Jumppanen Apr 18 '16 at 14:21
  • How this might help? This does not tell anything about column grouping. – danas.zuokas Apr 19 '16 at 06:56
  • Closest extension which I found. It seems that you have to write javascript so example how to do row grouping might help. – Mikael Jumppanen Apr 19 '16 at 06:58
  • I would look at this post [https://stackoverflow.com/questions/56142354/how-can-i-add-a-vertical-line-to-a-datatable](https://stackoverflow.com/questions/56142354/how-can-i-add-a-vertical-line-to-a-datatable) – kraggle May 06 '22 at 20:25

1 Answers1

10

You could add a css class that adds a border on the right of the cells and apply it to the relevant columns using the columnDefs options. For the header, you can set the class using the initComplete callback.

Here's an example:

library(shiny)
library(DT)
library(htmltools)

runApp(shinyApp(
  ui <- basicPage(
    tags$head(
      tags$style(HTML(".cell-border-right{border-right: 1px solid #000}"))),
    DT::dataTableOutput('table1')
  ),
  server = function(input, output) {
    output$table1 <- DT::renderDataTable({
      datatable(data.frame(a1 = 1, b1 = 2, a2 = 3, b2 = 4), rownames = FALSE,
                container = withTags(table(
                  class = 'display',
                  thead(
                    tr(
                      th(colspan = 2, 'g1'),
                      th(colspan = 2, 'g2')
                    ),
                    tr(
                      lapply(rep(c('a', 'b'), 2), th)
                    )
                  )
                )),options = list(initComplete = JS(
                  "function(settings, json) {",
                  "var headerBorder = [0,1];",
                  "var header = $(this.api().table().header()).find('tr:first > th').filter(function(index) {return $.inArray(index,headerBorder) > -1 ;}).addClass('cell-border-right');",
                  "}"),columnDefs=list(list(className="dt-right cell-border-right",targets=1))
      ))
    })
  }
))

The jquery selectors are used to select the first row of the header and the first th tag, so that the border is only added to the g1 cell.

NicE
  • 21,165
  • 3
  • 51
  • 68
  • Thank you @NicE for the answer. Could you show how can I add the line in the header row for any columns using indexes (like using `targets` for the table body)? – danas.zuokas Apr 21 '16 at 07:09
  • Sure, you can replace `th:first` by `th:eq(1)` and change the number in the `eq`, it's a `jquery selector`, more info [here](https://api.jquery.com/eq-selector/) – NicE Apr 21 '16 at 07:42
  • And what about several columns (like targets = c(0, 1))? Thanks. – danas.zuokas Apr 21 '16 at 08:32
  • I edited for this, you can use the `jquery` `filter` function, here it goes through the `th` cells of the header and adds a border if they are in the `headerBorder` array. You can probably build the `headerBorder` array using `paste` if the columns you want a border for a stored in an R vector. – NicE Apr 21 '16 at 09:01