我有一个闪亮的 R 应用程序,我想右键单击任意行并显示包含不同可操作项目的上下文菜单(打印右键单击行的数据)。
首次启动应用程序时,上下文菜单和可操作项目工作正常。 但是,单击“更新表”按钮(在这个可重现的示例中,只是更新/重新渲染数据表)后,右键单击时仍然会出现上下文菜单,但不同的可操作项目无法在仅显示的地方工作“未定义”而不是实际的行数据。
有谁可以解释为什么 JS() 回调函数中可操作项的行为在重新渲染数据表后不起作用?
我读过很多关于重新渲染输出后数据表的 ID 被覆盖的内容,也许回调函数无法正确指向新创建的 ID(通过参数“selector: '#mytable tr'”)。我不是当然,但如果这是原因,我仍然无法找到解决方法。
下面是完全可重现的示例:
library(shiny)
library(DT)
c1 <- c(
"$.contextMenu({",
"selector: '#mytable tr',",
"trigger: 'right',",
"callback: function(key, options) {",
"var row = table.row(options.$trigger);",
"var data = row.data();",
"var m = 'clicked: ' + key + ' ' + data;",
"var newtab = window.open('','anotherWindow', 'width=750,height=600');",
"newtab.document.write('<p> Below is the row data! </p>', '<br>',data);",
"},",
"items: {",
"'showdata': {name:'Show row data', icon: 'fa-regular fa-folder'},",
"'showsamedata': {name:'Show same row data again', icon: 'fa-regular fa-folder'}",
"}",
"})"
)
ui <- fluidPage(
tags$head(
tags$link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.contextMenu.min.css"),tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.contextMenu.min.js"),tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.ui.position.js"),tags$script(src="https://kit.fontawesome.com/293ef49cbe.js")
),
DTOutput("mytable"),
actionButton(inputId = "update",
width = "150px",
#style = "height:35px;border:3px;border-style:double;border-color:black;",
label = div(style="vertical-align:middle;font-weight:bold","Update table"))
)
server <- function(input, output) {
#initial rendering
output$mytable <- renderDataTable({
datatable(iris, callback = JS(c1))
})
#re-rendering
observeEvent(input$update, {
output$mytable <- renderDataTable({
datatable(iris, callback = JS(c1))
})
})
}
shinyApp(ui, server)
我尝试使用 proxyDataTables 并使用 drawCallback 函数,但没有成功。此外,我的应用程序需要能够使用回调函数而无需代理,因为实际应用程序通过具有许多过滤器的函数重新创建整个数据表,然后最终得到渲染。
我希望回调函数即使在更新/重新渲染数据表之后也能完全工作。
我不知道为什么会有这种行为。它的工作原理如下,没有回调:
library(shiny)
library(DT)
c1 <- c(
"$(document).ready(function() {",
" $.contextMenu({",
" selector: '#mytable tr',",
" trigger: 'right',",
" callback: function(key, options) {",
" var tbl = $('#mytable').find('table').DataTable();",
" var row = tbl.row(options.$trigger);",
" var data = row.data();",
" var m = 'clicked: ' + key + ' ' + data;",
" var newtab = window.open('','anotherWindow', 'width=750,height=600');",
" newtab.document.write('<p> Below is the row data! </p>', '<br>',data);",
" },",
" items: {",
" 'showdata': {name:'Show row data', icon: 'fa-regular fa-folder'},",
" 'showsamedata': {name:'Show same row data again', icon: 'fa-regular fa-folder'}",
" }",
" });",
"});"
)
js <- paste0(c1, collapse = "\n")
ui <- fluidPage(
tags$head(
tags$link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.contextMenu.min.css"),tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.contextMenu.min.js"),tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.ui.position.js"),
tags$script(src="https://kit.fontawesome.com/293ef49cbe.js"),
tags$script(HTML(js))
),
DTOutput("mytable"),
actionButton(
inputId = "update",
width = "150px",
#style = "height:35px;border:3px;border-style:double;border-color:black;",
label = div(style="vertical-align:middle;font-weight:bold","Update table")
)
)
server <- function(input, output) {
#initial rendering
output$mytable <- renderDataTable({
datatable(iris)
})
#re-rendering
observeEvent(input$update, {
output$mytable <- renderDataTable({
datatable(iris)
})
})
}
shinyApp(ui, server)