如何从数据表内的自定义按钮调用 JavaScript 函数?

问题描述 投票:0回答:1

我已经下载并希望将以下 JavaScript 库合并到我的 R Shiny 应用程序中:GitHub 链接

正如您在下面的代码片段中看到的,我已将

sequence-viewer.min.js
文件合并到 UI 的头部。此外,使用
tags$div(id="sequence-viewer")
我可以在网页源中看到相应的
<div>
标签,所以到目前为止我认为一切都很好。

使用以下代码,我构建并渲染了一个带有序列的示例数据表。从最后一列的链接中,我想使用数据表的序列动态更改

var seq=new Sequence('');
的值,并在每次单击链接时在
sequence-viewer
div 中绘制结果。

library(shiny)

ui <- fluidPage(
    theme = shinytheme("yeti"),
    useShinyjs(),
    useShinyalert(),
    tags$head(tags$script(src = "handlebars.js"),
              tags$script(src = "sequence-viewer.min.js")),
    mainPanel( DT::dataTableOutput("DTtable"),
               br(),
               tags$div(id="sequence-viewer")
             )
    )

server <- function(input, output) {

exp1 <- reactive({
    tbl <- as.data.frame(c("MALWMPGPGAGSL", "MALKYTFDCVBJUYGFGPGAGSL", "IUYTFVBNMKIUYF"))
    names(tbl) <- "Sequence"
    tbl$link <- createLink(tbl$Sequence)
    return(tbl)
})

createLink <- function(val) {
    link <- paste0("<a href='#' onclick='var seq=new Sequence('",val,"'); seq.render('#sequence-viewer');'>Show seq</a>", sep="")
    return(link)
}

output$DTtable <- DT::renderDataTable({ exp1() 
    }, escape = FALSE, options = list(scrollX = TRUE, dom = 'lfrtip', pageLength = 10, 
lengthMenu=c(10, 25, 50, 100)), rownames = FALSE)

}

# Run the application 
shinyApp(ui = ui, server = server)

我已经阅读了许多关于如何在 R Shiny 中运行自定义

javascript
代码的线程和教程,但是我找到的所有示例都在
ui
中进行调用,而不是在
server
侧,可以吗?请告诉我如何获得所需的输出?

注意: 根据 github 页面上的说明,需要依赖项

jquery
handlebars
bootstrap.min.css
。我想只要
handlebars.js
就必须手动添加,因为 R Shiny 已经带有 bootstrap 和 jquery 了?

更新1:好的,我想我现在快到了。感谢 @YBS 的评论,我设法了解如何使用外部 javascript 库。如果我单击

actionLink
,下面的代码可以正常工作,但是当单击我使用
createLink
函数创建的数据表内的自定义链接时,它不起作用。我在浏览器的控制台中收到以下异常:Uncaught ReferenceError: js$seque is not Defined。有什么想法为什么会发生这种情况吗?

library(shiny)
library(shinyjs)

jsCode = '
shinyjs.seque = function(params) {
  var defaultParams = {
   seq : "LKJHGFVBJKUGFKGFFGHJKUYTRFGHJUYTGHJIUYT"
 };
 params = shinyjs.getParams(params, defaultParams);

 var seq=new Sequence(params.seq);
 seq.render("#sequence-viewer");
}
'


ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode, functions = c("seque")),
tags$head(tags$script(src = "handlebars.js"),
          tags$script(src = "sequence-viewer.min.js")
          ),

mainPanel( DT::dataTableOutput("DTtable"),
           br(),
           actionLink(inputId = "action", 
                        label = "action"),
           br(),
           tags$div(id="sequence-viewer")
    )

 )

server <- function(input, output) {

exp1 <- reactive({
    tbl <- as.data.frame(c("MALWMPGPGAGSL", "MALKYTFDCVBJUYGFGPGAGSL", "IUYTFVBNMKIUYF"))
    names(tbl) <- "Sequence"
    tbl$link <- createLink(tbl$Sequence)
    return(tbl)
})

createLink <- function(val) {
    link <- paste0("<a href='#' onclick='js$seque(",val,")' id='",val,"' class='action-button shiny-bound-input'>Show sequence</a>", sep="")
    return(link)
}

observeEvent(input$action, {
    js$seque("MALKYTFDCVBJUYGFGPGAGSL")
})

output$DTtable <- DT::renderDataTable({ 
    exp1()
}, escape = FALSE, options = list(scrollX = TRUE, dom = 'lfrtip', pageLength = 10, 
                                  lengthMenu=c(10, 25, 50, 100)), rownames = FALSE)

 }

# Run the application 
shinyApp(ui = ui, server = server)

更新2:

经过几个小时的调试,我设法通过将

createLink
函数中按钮的 onclick='js$seque(",val,")' 事件替换为以下内容来解决问题:
onclick='shinyjs.seque(\"",val,"\")'
- 或者更清晰的
onclick='shinyjs.seque(JSON.stringify(val))'

简而言之,此时

js$seque
调用是不正确的,我必须将这一行替换为
shinyjs.seque
,即 JS 中函数的实际名称。另一方面,典型的 R
actionButton
元素需要
js$seque
。我将尝试编写清晰的 MRE 代码并将其作为该线程的答案提供。

r shiny dt shinyjs
1个回答
2
投票

在您的情况下使用

shinyjs
是一种矫枉过正,因为您不想从 R 调用 JS 函数,而是通过客户端调用。因此,您可以像这个玩具示例一样简单地使用纯 JavaScript:

library(shiny)

js <- HTML("seque = function(seq) {
               alert(seq);
           }")

ui <- fluidPage(tags$head(tags$script(js)), 
                tags$a(hreg = "#", onclick = "seque('test message')",
                       "Click me to send test message"))

server <- function(...) {}

shinyApp(ui, server)

不要误会我的意思

shinyjs
:有其优点,但典型的用例是您想要从 R 端触发 JavaScript 代码,如本例所示:

library(shiny)
library(shinyjs)

js_code <- HTML("shinyjs.seque = function(par) {
               var def_par = {seq: 'test message'};
               par = shinyjs.getParams(par, def_par);
               alert(par.seq);
           }")

ui <- fluidPage(useShinyjs(),
                extendShinyjs(text = js_code, functions = "seque"),
                actionButton("click", "Click me to send message"))

server <- function(input, output, session) {
   observeEvent(input$click,  {
      js$seque("test message from R")
   })
}

shinyApp(ui, server)

在此示例中,我使用

shinyjs
直接从 R 调用 JS,而在前面的示例中,JS 是通过
onclick
调用的。

对于您的示例,您可以在表中使用

actionLink
并添加一个观察者,并在其中调用
js$queue
但由于每行只有一个链接,因此编码可能很棘手(但并非不可能)(基本上您需要动态听众),

因此,像您的示例一样依赖纯 JS (

onclick
) 可能是更好的选择,但这样您就不需要
shinyjs

© www.soinside.com 2019 - 2024. All rights reserved.