我已经下载并希望将以下 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 代码并将其作为该线程的答案提供。
在您的情况下使用
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
。