【发布时间】:2018-08-02 10:16:41
【问题描述】:
我有一个复杂的 Shiny 应用程序,需要使用自定义 JavaScript 代码。该应用程序由在具有不同名称空间的多个位置调用的模块组成。我需要一些 JavaScript 代码与 R 代码一起“模块化”,即使用模块名称空间。我可以通过创建一个包含 JS 代码的自定义字符串并使用 shinyjs::runjs() 函数(下面的示例)执行它来使其工作。对于给定的示例,这是一个公平的解决方案。然而,将更复杂的超过 100 行 JavaScript 代码放入粘贴有标识符的字符串中似乎非常容易出错且不是最佳解决方案(缺乏突出显示、令人痛苦的格式化等)。有没有更好的方法来达到同样的效果?
library(shiny)
library(shinyJS)
myModuleUI <- function(id) {
ns <- NS(id)
tagList(
div(id = ns("clickableElement"), class = "btn btn-primary", "Click Me"),
div(id = ns("highlightableElement"), "This (and only this!) text should be highlighted on click")
)
}
myModule <- function(input, output, session) {
ns <- session$ns
shinyjs::runjs(paste0("
$('#", ns("clickableElement"), "').click(function() {
$('#", ns("highlightableElement"), "').css('background', 'yellow');
})
"))
}
ui <- fluidPage(
useShinyjs(),
tabsetPanel(
tabPanel(
"Instance 1",
myModuleUI("one")
),
tabPanel(
"Instance 2",
myModuleUI("two")
)
)
)
server <- function(input, output) {
callModule(myModule, "one")
callModule(myModule, "two")
}
shinyApp(ui = ui, server = server)
更新
为了将来参考,我决定分享我最终实施的解决方案。我最终为每个模块创建了一个 JS 文件,其中包含一个将命名空间作为唯一参数的函数。此函数使用此命名空间创建所有需要的对象和绑定。然后我在模块的开头使用shinyjs 调用该单个函数。这允许我将 JS 代码保存在一个单独的文件中,这解决了最初的问题并使代码易于管理(尤其是如果您有很多 JS 代码)。
app.R
library(shiny)
library(shinyjs)
myModuleUI <- function(id) {
ns <- NS(id)
tagList(
div(id = ns("clickableElement"), class = "btn btn-primary", "Click Me"),
div(id = ns("highlightableElement"), "This (and only this!) text should be highlighted on click")
)
}
myModule <- function(input, output, session) {
ns <- session$ns
shinyjs::runjs(paste0("myModuleJS('", ns(""), "');"))
}
ui <- fluidPage(
useShinyjs(),
tags$head(
tags$script(src = "myModuleJS.js")
),
tabsetPanel(
tabPanel(
"Instance 1",
myModuleUI("one")
),
tabPanel(
"Instance 2",
myModuleUI("two")
)
)
)
server <- function(input, output) {
callModule(myModule, "one")
callModule(myModule, "two")
}
shinyApp(ui = ui, server = server)
www/myModuleJS.js
function myModuleJS(ns) {
$('#' + ns + 'clickableElement').click(function() {
$('#' + ns + 'highlightableElement').css('background', 'yellow');
});
}
【问题讨论】:
-
使用命名空间作为消息的一部分向浏览器发送自定义消息,以便它找到正确的客户端?
标签: javascript r shiny