6

I’m stuck with trying to include something like a tooltip or popover with additional info when the user hovers over / clicks on the row names of a datatable, so they don’t have to look up some definitions, which I currently have on a different tabPanel. Here's a working example:

server.R:

library(shiny)
library(DT)
library(shinyBS)

# Define server for the Shiny app
shinyServer(function(input, output,session) {

tdata <- as.data.frame(iris)

# Render table here 
output$mytable <- DT::renderDataTable(DT::datatable(

   tdata[1:5,],

   options = list(paging = FALSE, searching = FALSE, info = FALSE, sort = FALSE,
                 columnDefs=list(list(targets=1:4, class="dt-right")) ),

   rownames = paste("rowname",1:5),

   container = htmltools::withTags(table(
      class = 'display',
      thead(
         tr(lapply(rep(c('ratios','name1', 'name2', 'name3','name4','name5'), 1),th))
      )
   ))
))

}) # end of shinyServer function

ui.R:

library(shiny)
library(DT)
library(shinyBS)

shinyUI(
   mainPanel(
      DT::dataTableOutput("mytable")
   )   
)      

Please note that I have seen the following discussion topics, but without success: R shiny mouseover text for table columns, as well as Add bootstrap tooltip to column header in shiny app So I'm thinking either something within the DT-package options, or something using the shinyBS package (like 'bsTooltip') or add some HTML or JS. This tooltip/popover feature does not seem to be naturally supported by Shiny for within datatables...!?

Community
  • 1
  • 1
humuskopf
  • 115
  • 1
  • 5

2 Answers2

7

This code works but running in client side mode. To make it simpler I have used the first five rows of the iris dataset, but I guess the idea is clear. If you hover over the row names the tooltip will be displayed.

ui.R

    library(shiny)
    library(DT)
    shinyUI(
            mainPanel(
                    DT::dataTableOutput("tbl")
            )   
    )    

server.R

    library(shiny)
    library(DT)
    shinyServer(function(input, output,session) {
            output$tbl = DT::renderDataTable(
                    datatable(iris[1:5, ], callback = JS("
                                    var tips = ['First row name', 'Second row name', 'Third row name',
                                    'Fourth row name', 'Fifth row name'],
                                    firstColumn = $('#tbl tr td:first-child');
                                    for (var i = 0; i < tips.length; i++) {
                                    $(firstColumn[i]).attr('title', tips[i]);
                                    }")), server = FALSE)
    }) 
Valter Beaković
  • 3,140
  • 2
  • 20
  • 30
  • great, that works! I had cooked up something like that from the example for column names, but I had forgotten the server=FALSE! thanks for your help, Valter! – humuskopf Oct 12 '16 at 21:06
1

It didn't work because your code didn't use the title attribute, that is used for displaying the label on hover.

container = htmltools::withTags(table(
  class = 'display',
  thead(
    tr(lapply(rep(c('ratios','name1', 'name2', 'name3','name4','name5'), 1),th))
  )
))
# OUTPUT OF CONTAINER
#<table class="display">
#  <thead>
#    <tr>
#      <th>ratios</th>
#      <th>name1</th>
#      <th>name2</th>
#      <th>name3</th>
#      <th>name4</th>
#      <th>name5</th>
#    </tr>
#  </thead>
#</table>

I changed your code to the following (using the title attribute), and now it should work:

Label is set with columnLabels <- paste0("label", 1:6) and other than that only container is changed.

  # Render table here 
  output$mytable <- DT::renderDataTable({
    columnLabels <- paste0("label", 1:6)

    DT::datatable(
      tdata[1:5,],

      options = list(paging = FALSE, searching = FALSE, info = FALSE, sort = FALSE,
                     columnDefs=list(list(targets=1:4, class="dt-right")) ),

      rownames = paste("rowname",1:5),

      container = htmltools::withTags(table(
        class = 'display',
        thead(
          #tags$th(title=active_columns[i], colnames(data)[i])
          tr(apply(data.frame(colnames=c('ratios','name1', 'name2', 'name3','name4','name5'), labels=columnLabels), 1,
                   function(x) th(title=x[2], x[1])))
        )
      ))
    )
  })
# OUTPUT OF CONTAINER
#<table class="display">
#  <thead>
#    <tr>
#      <th title="label1">ratios</th>
#      <th title="label2">name1</th>
#      <th title="label3">name2</th>
#      <th title="label4">name3</th>
#      <th title="label5">name4</th>
#      <th title="label6">name5</th>
#    </tr>
#  </thead>
#</table>
GyD
  • 3,902
  • 2
  • 18
  • 28
  • this produced column labels, not row labels. I've tried to adapt it to do the same thing for rownames without success, but didn't try for too long now as the other solution posted by Valter above worked. Thanks though! – humuskopf Oct 12 '16 at 21:28
  • for some reason I thought it was about colnames, sorry. :) – GyD Oct 20 '16 at 06:03