使用 initComplete 在 Shiny 应用程序中使用 Javascript 定位特定 DT::datatable table
Target specific DT::datatable table with Javascript in Shiny app using initComplete
假设我们有一个带有两个 DT
table 的 Shiny 应用,我们想在呈现 table 之后用一些 Javascript 对其进行修改.我们在每个 table 中将不同的上标附加到 header;我们在 table 1 上附加一个上标 '1',在 table 2 上附加一个上标 '2'。这个 JS 是使用 initComplete
触发的,即,当 table 是渲染。
我的 JS 技能不存在,所以我目前正在 select 将 table header 添加到 th:contains(<header-string>)
。例如,将上标附加到包含字符串 'Sepal':
的 table header
jsc <- '
function(settings, json) {
$("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
由于我们需要为不同的 table 设置不同的上标,因此我们需要定义单独的 Javascript 来为每个 table 触发。这个问题是 table headers 都包含我要查找的字符串,导致两个上标都附加到 table headers.
假设不同的 table 将始终在相关的 table header 中包含相同的字符串(因此 th:contains
将不是一个可行的选择 - - table header 可能完全相同),我们如何 select 一个特定的 table 来应用 Javascript?我们不能在 Shiny 应用程序中为 datatable
调用提供 elementId
,例如,
output$table1<- renderDT({datatable(iris, elementId = 'table1')})
导致警告
Warning in renderWidget(instance) :
Ignoring explicitly provided widget ID "table1"; Shiny doesn't use them
下面是一个可重现的例子。两个 table 具有相同的列名,因此 Javascript 将两个上标附加到每个 table 的 Sepal.Length
header。期望的输出是第一个 table 的 Sepal.Length
header 带有上标“1”,第二个 table 的 Sepal.Length
header 带有上标“2”,而当前示例将“12”附加到 table 的 headers.
有趣的是,当应用程序在 RStudio 查看器中打开时,只有第一个 initComplete
是 运行,因此两个 table header 都有一个上标 '1 '.我忽略了这一点并在 Firefox 和 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)
请注意,我知道我们可以直接将 <sup>1</sup>
写入 table header 中 escape = FALSE
,但还有其他 JS 函数可以在 table 上执行,所以这种方法不会被 suitable。感谢您的任何建议。
首先,options
必须是一个列表:
datatable(iris[, c('Species', 'Sepal.Length')],
options = list(
initComplete = JS(jsc)
)
)
现在,您可以通过在 jQuery 选择器中提供 ID 来定位 table:
jsc <- '
function(settings, json) {
$("#table1 th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
否则,$("th:contains(\'Sepal\')")
将选择所有 th
,其中包含 Sepal
,并且可以在整个页面上找到。
但是这种方式改id需要改JS代码。更实际的做法是:
jsc <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
完整代码:
library(shiny)
library(DT)
jsc <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
jsc2 <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("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 = list(
initComplete = JS(jsc)
)
)
})
output$table2 <- renderDT({
datatable(iris[, c('Species', 'Sepal.Length')],
options = list(
initComplete = JS(jsc2)
)
)
})
}
shinyApp(ui, server)
假设我们有一个带有两个 DT
table 的 Shiny 应用,我们想在呈现 table 之后用一些 Javascript 对其进行修改.我们在每个 table 中将不同的上标附加到 header;我们在 table 1 上附加一个上标 '1',在 table 2 上附加一个上标 '2'。这个 JS 是使用 initComplete
触发的,即,当 table 是渲染。
我的 JS 技能不存在,所以我目前正在 select 将 table header 添加到 th:contains(<header-string>)
。例如,将上标附加到包含字符串 'Sepal':
jsc <- '
function(settings, json) {
$("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
由于我们需要为不同的 table 设置不同的上标,因此我们需要定义单独的 Javascript 来为每个 table 触发。这个问题是 table headers 都包含我要查找的字符串,导致两个上标都附加到 table headers.
假设不同的 table 将始终在相关的 table header 中包含相同的字符串(因此 th:contains
将不是一个可行的选择 - - table header 可能完全相同),我们如何 select 一个特定的 table 来应用 Javascript?我们不能在 Shiny 应用程序中为 datatable
调用提供 elementId
,例如,
output$table1<- renderDT({datatable(iris, elementId = 'table1')})
导致警告
Warning in renderWidget(instance) : Ignoring explicitly provided widget ID "table1"; Shiny doesn't use them
下面是一个可重现的例子。两个 table 具有相同的列名,因此 Javascript 将两个上标附加到每个 table 的 Sepal.Length
header。期望的输出是第一个 table 的 Sepal.Length
header 带有上标“1”,第二个 table 的 Sepal.Length
header 带有上标“2”,而当前示例将“12”附加到 table 的 headers.
有趣的是,当应用程序在 RStudio 查看器中打开时,只有第一个 initComplete
是 运行,因此两个 table header 都有一个上标 '1 '.我忽略了这一点并在 Firefox 和 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)
请注意,我知道我们可以直接将 <sup>1</sup>
写入 table header 中 escape = FALSE
,但还有其他 JS 函数可以在 table 上执行,所以这种方法不会被 suitable。感谢您的任何建议。
首先,options
必须是一个列表:
datatable(iris[, c('Species', 'Sepal.Length')],
options = list(
initComplete = JS(jsc)
)
)
现在,您可以通过在 jQuery 选择器中提供 ID 来定位 table:
jsc <- '
function(settings, json) {
$("#table1 th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
否则,$("th:contains(\'Sepal\')")
将选择所有 th
,其中包含 Sepal
,并且可以在整个页面上找到。
但是这种方式改id需要改JS代码。更实际的做法是:
jsc <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
完整代码:
library(shiny)
library(DT)
jsc <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
}
'
jsc2 <- '
function(settings, json) {
var $table = $(this.api().table().node());
$table.find("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 = list(
initComplete = JS(jsc)
)
)
})
output$table2 <- renderDT({
datatable(iris[, c('Species', 'Sepal.Length')],
options = list(
initComplete = JS(jsc2)
)
)
})
}
shinyApp(ui, server)