使用initComplete

问题描述

假设我们有一个带有两个DT表的Shiny应用程序,我们希望在渲染表后使用一些Javascript对其进行修改。我们在每个表的标题中附加一个不同的上标;我们在表1上添加上标'1',在表2上添加上标'2'。此JS是使用initComplete触发的,即在渲染表时触发。

我的JS技能不存在,因此我目前正在选择要附加到th:contains(<header-string>)的表头。例如,将上标附加到包含字符串'Sepal'的表标题中:

jsc <- '
    function(settings,json) {
        $("th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
    }
'

由于我们需要为不同的表使用不同的上标,因此我们需要定义单独的Javascript以为每个表触发。问题是表头都包含我要查找的字符串,导致两个上标都附加到两个表头上。

假设不同的表在相关的表头中始终包含相同的字符串(因此th:contains将不是一个可行的选择-表头可能完全相同),我们如何选择适用于Java的特定表?我们无法在“闪亮”应用程序中为elementId调用提供datatable,例如

output$table1<- renderDT({datatable(iris,elementId = 'table1')})

产生警告

renderWidget(instance)中的警告: 忽略显式提供的小部件ID“ table1”;闪亮不使用它们

下面是一个可复制的示例。这两个表具有相同的列名,因此Javascript将这两个上标附加到每个表的Sepal.Length标题中。理想的输出结果是第一个表的Sepal.Length标头带有上标“ 1”,第二个表的Sepal.Length标头带有上标“ 2”,而当前示例在两个表的后缀中都附加了“ 12”标头。

很有趣,当在RStudio Viewer中打开应用程序时,仅运行第一个initComplete,因此两个表头均带有上标'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[,options(
                initComplete = JS(jsc2)  
            )
        )
    })
}

options(shiny.launch.browser = TRUE)
shinyApp(ui,server)

请注意,我知道我们可以使用<sup>1</sup>escape = FALSE直接写到表头中,但是要在表上执行其他JS函数,因此这种方法不适合。谢谢您的任何建议。

解决方法

首先,options必须是一个列表:

datatable(iris[,c('Species','Sepal.Length')],options = list(
            initComplete = JS(jsc)
          )
)

现在,您可以通过在jQuery选择器中提供ID来定位表:

jsc <- '
    function(settings,json) {
        $("#table1 th:contains(\'Sepal\')").append(\'<sup>1</sup>\');
    }
'

否则,$("th:contains(\'Sepal\')")选择包含th的所有Sepal,这些jsc <- ' function(settings,json) { var $table = $(this.api().table().node()); $table.find("th:contains(\'Sepal\')").append(\'<sup>1</sup>\'); } ' 可以在整个页面上找到。

但是,如果您更改ID,则这种方法需要更改JS代码。这样做更实用:

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[,options = list(
                initComplete = JS(jsc)
              )
    )
  })
  
  output$table2 <- renderDT({
    datatable(iris[,options = list(
                initComplete = JS(jsc2)  
              )
    )
  })
}

shinyApp(ui,server)

完整代码:

path = """{'ResponseMetadata': {'Flag': 'Processed','Message': 'File Ingested successfully','INGEST_PATH': ['inward/emr_batch/manual_cars/xy99',""manual_cars/xy99/2020/08/12/145938/ABC KPI's Jan 2018.csv""]}}"""