Let's say we have a Shiny app with two DT
tables, which we would like to modify with some Javascript after the tables have been rendered. We are appending a different superscript to a header in each table; we append a superscripted '1' to table 1, and a superscripted '2' to table 2. This JS is triggered using initComplete
, i.e., when the table is rendered.
My JS skills are nonexistent, so I am currently selecting the table header to append to with th:contains(<header-string>)
. For example, appending a superscript to a table header containing the string 'Sepal':
jsc <- '
function(settings, json) {
$("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
Since we need a different superscript for the different tables, we need to define separate Javascript to trigger for each table. This issue is that the table headers both contain the string that I am looking for, resulting in both superscripts being appended to both table headers.
Assuming that the different tables will always contain the same string in the relevant table header (and therefore that th:contains
will not be a viable option -- the table headers could be exactly the same), how can we select a specific table to apply the Javascript to? We can't supply an elementId
to the datatable
call in a Shiny app, e.g.,
output$table1<- renderDT({datatable(iris, elementId = 'table1')})
results in the warning
Warning in renderWidget(instance) : Ignoring explicitly provided widget ID "table1"; Shiny doesn't use them
A reproducible example is below. The two tables have identical column names, so the Javascript is appending both superscripts to the Sepal.Length
header of each table. The desired output is to have the first table's Sepal.Length
header with a superscripted '1', and the second table's Sepal.Length
header with a superscripted '2', while the current example appends '12' to both table's headers.
Funnily enough, when the app opens in the RStudio Viewer, only the first initComplete
is run, so both table headers have a superscripted '1'. I am ignoring this and checking results on Firefox and Chrome.
library(shiny)
library(DT)
jsc <- '
function(settings, json) {
$("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
jsc2 <- '
function(settings, json) {
$("th:contains(\'Sepal\')").append(\'<sup>2</sup>\');
}
'
ui <- {
fluidPage(
fluidRow(
column(6,
DTOutput('table1')
),
column(6,
DTOutput('table2')
)
)
)
}
server <- function(input, output, session) {
output$table1 <- renderDT({
datatable(iris[, c('Species', 'Sepal.Length')],
options(
initComplete = JS(jsc))
)
})
output$table2 <- renderDT({
datatable(iris[, c('Species', 'Sepal.Length')],
options(
initComplete = JS(jsc2)
)
)
})
}
options(shiny.launch.browser = TRUE)
shinyApp(ui, server)
Please note that I'm aware we can could directly write the <sup>1</sup>
into the table headers with escape = FALSE
, but there are other JS functions to execute on the table so this approach will not be suitable. Thank you for any advice.