2015-09-19 2 views
1

Я пытаюсь выделить раздел, содержащий значение сеанса session$sendCustomMessage, чтобы я мог отправить сообщение при нажатии на ActionButton. Пользователь загружает файл, затем становится видимым ActionButton. Только при нажатии кнопки, мы должны ввести изолированный раздел server.R. После этого выполняется некоторое вычисление, и файл возвращается пользователю. Однако я не могу правильно изолировать, и файл возвращается даже без нажатия ActionButton. Вот мое приложение:R shiny: выделить переменные сеанса

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.") 
)) 

ответ

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)) 
    }) 
}) 
+0

хорошая идея с разделения вещей. Тем не менее, кнопка клика будет непрерывно увеличиваться, поэтому просто проверить, равно ли она 0, недостаточно. – Cauchy

+0

Если вы хотите поддерживать более одной загрузки, имеет смысл извлечь логику обработки и обработчик кнопок. – zero323