Reputation: 1747
I am trying to isolate a section containing a session value session$sendCustomMessage
so that I can send a message when an ActionButton
is clicked. The user uploads a file, then the ActionButton
becomes visible. Only when the button is clicked, should we enter the isolated section of server.R
. After this, some computation is done, and a file is returned to the user. However, I am failing to isolate properly, and the file is being returned even without clicking the ActionButton
. Here is my App:
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.")
))
Upvotes: 1
Views: 928
Reputation: 330423
Your problems are completely unrelated to the session variables. The only event that actually triggers the computation here is input$upload
. If upload is empty your code hits following lines
if (is.null(inFile))
return(NULL)
and everything works as expected. If file has been uploaded your program reaches isolate block. Any variable that is enclosed using isolate
is not considered to be a dependency so following part of your code has no effect at all, and assumption you make in the comment is simply wrong:
isolate({
# Make this isolated section dependent on the start_proc ActionButton
input$start_proc
...
})
Even if you place input$start_proc
outside the isolate
block your code won't work as expected since you don't check if action button has been clicked at all.
One way to make your code work is to separate upload and download logic as follows:
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))
})
})
Upvotes: 3