如何解决R Shiny:如何从数据表中的自定义按钮调用JavaScript函数
我已经下载了以下JavaScript库,并希望将其集成到我的R Shiny应用程序中:GitHub link
如下面的代码片段所示,我已将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
而不是{{ 1}}方面,您能建议我如何获得所需的输出吗?
注意::根据github页面上的说明,需要依赖项server
,jquery
和handlebars
。我想假设R Shiny已经随附了引导程序和jquery,只需手动添加bootstrap.min.css
即可。
更新1:好的,我想我已经快到了。由于@YBS的评论,我设法获得了如何使用外部javascript库的想法。如果单击handlebars.js
,下面的代码可以正常工作,但是单击使用actionLink
函数在Datatable中创建的自定义链接时,以下代码将无法正常工作。我在浏览器的控制台中收到以下异常:未捕获的ReferenceError:未定义js $ seque 。任何想法为什么会这样?
createLink
更新2:
经过许多小时的调试,我设法通过以下方法替换了 createLink 函数中按钮的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$script(src = "sequence-viewer.min.js")
),actionLink(inputId = "action",label = "action"),tags$div(id="sequence-viewer")
)
)
server <- function(input,"IUYTFVBNMKIUYF"))
names(tbl) <- "Sequence"
tbl$link <- createLink(tbl$Sequence)
return(tbl)
})
createLink <- function(val) {
link <- paste0("<a href='#' onclick='js$seque(",")' id='","' class='action-button shiny-bound-input'>Show sequence</a>",sep="")
return(link)
}
observeEvent(input$action,{
js$seque("MALKYTFDCVBJUYGFGPGAGSL")
})
output$DTtable <- DT::renderDataTable({
exp1()
},rownames = FALSE)
}
# Run the application
shinyApp(ui = ui,server = server)
事件:onclick='js$seque(",")'
-甚至更清晰的onclick='shinyjs.seque(\"","\")'
简而言之,此时的onclick='shinyjs.seque(JSON.stringify(val))'
调用是不正确的,我不得不用js$seque
替换这一行,即用JS中函数的实际名称。另一方面,典型的R shinyjs.seque
元素需要actionButton
。我将尝试编写清晰的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
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。