我正在尝试隔离包含会话值session$sendCustomMessage
的部分,以便在单击ActionButton
时发送消息。用户上传文件,然后ActionButton
变为可见。只有在单击按钮时,我们才应输入server.R
的隔离部分。在此之后,完成一些计算,并将文件返回给用户。但是,我无法正确隔离,即使没有单击ActionButton
也会返回文件。这是我的应用程序:
server.R:
library(shiny)
shinyServer(function(input, output, session) {
observe({
inFile <- input$upload
if (is.null(inFile))
return(NULL)
# Send message indicating that the file is now uploaded
session$sendCustomMessage("upload_ready", list(fileSize=0))
# Read the .csv file
df = readLines(inFile$datapath)
# Isolate this section from the reactive context.
# But this is executing even if the Action Button is not
# clicked
isolate({
# Make this isolated section dependent on the start_proc ActionButton
input$start_proc
output$data_file <- downloadHandler(
filename = function() {
paste('probabilities-', Sys.Date(), '.txt', sep='')
}
,
content = function(file1) {
writeLines(df, con = file1)
}
)
# I think this is the problem, the session changes even if the
# action button is not clicked, and this is why the code is going
# into this section.
session$sendCustomMessage("download_ready", list(fileSize=0))
})
})
})
ui.R
library(shiny)
library(shinyBS)
shinyUI(fixedPage(
singleton(tags$head(HTML(
'
<script type="text/javascript">
$(document).ready(function() {
// disable download at startup. data_file is the id of the downloadButton
$("#data_file").attr("disabled", "true").attr("onclick", "return false;");
// Disable start_prob at the beginning
$("#start_proc").hide();
// When uploaded file is ready, give the option to start process
Shiny.addCustomMessageHandler("upload_ready", function(message) {
$("#start_proc").show();
});
// When the start_proc button is clicked, hide the button and disable
//
$("#start_proc").click(function(){
$("#start_proc").hide();
$("#upload").prop("disabled", true);
});
// Show the option to download the file when the download is ready.
// Also hide the button stat_proc and reactivate the option to upload
// a file.
Shiny.addCustomMessageHandler("download_ready", function(message) {
$("#upload").prop("disabled", false);
$("#data_file").removeAttr("disabled").removeAttr("onclick").html(
"<i class=\\"fa fa-download\\"></i>Download Ready");
});
})
</script>
'
))),
fileInput("upload", ""),
bsButton("start_proc", h5("Compute Probability\n"), size = "extra-small", style = "primary"),
downloadButton("data_file"),
helpText("Download will be available once the processing is completed.")
))
答案 0 :(得分:3)
您的问题与会话变量完全无关。实际触发计算的唯一事件是input$upload
。如果上传为空,则代码会跟随以下行
if (is.null(inFile))
return(NULL)
一切都按预期工作。如果文件已上传,则程序到达隔离块。使用isolate
括起来的任何变量都不被视为依赖项,因此在部分代码完全没有效果之后,假设您在注释中做出的假设完全错误:
isolate({
# Make this isolated section dependent on the start_proc ActionButton
input$start_proc
...
})
即使您将input$start_proc
放在isolate
块之外,您的代码也无法正常工作,因为您根本没有检查是否已点击操作按钮。
使代码工作的一种方法是按如下方式分离上传和下载逻辑:
shinyServer(function(input, output, session) {
raw <- reactive({
inFile <- input$upload
if (is.null(inFile)) return()
# Read the .csv file
readLines(inFile$datapath)
})
observe({
if (is.null(raw())) return() # If input empty return
# Send message indicating that the file is now uploaded
session$sendCustomMessage("upload_ready", list(fileSize=0))
})
df <- eventReactive(
input$start_proc, # Button clicked
{raw()} # Send data to download handler
)
observe({
if (is.null(df())) return() # In "preprocessed" data empty return
output$data_file <- downloadHandler(
filename = function() {
paste('probabilities-', Sys.Date(), '.txt', sep='')
},
content = function(file1) {
writeLines(df(), con = file1)
}
)
# And send meassage
session$sendCustomMessage("download_ready", list(fileSize=0))
})
})