3

I have a form with two different actions. The first one is to upload a file and the second is for an example. When I click one of these my app does something, but the server saves the information of a click and no change until I click on the other button.

For example, if I click the upload button without choose a file, it does nothing, but if I choose a file, the server uploads the file and start to process it without clicking on the upload button because the server has saved the past click. I want to know if is possible to reset the value for each click.

Index.html

<form class="span12 menu-med-upload">
 <div class="row-fluid">
  <h3>Upload File .fasta</h3>
  <div class="custom-input-file btn btn-inverse">
   <input type="file" size="1" name="fileFasta" id="fileFasta" class="input-file" />
   Select File
  </div>
  <img src="/static/img/check.png" class = "custom-input-check">
  <div class="span12"></div>
  <textarea class = "span12" rows  = "10" style="resize: none;" id="textAreaFasta">
  </textarea>
 </div>
 <button id="uploadFasta" type="button" class="btn btn-inverse action-button" >Upload    File</button>
 <button id="exampleFasta" type="button" class="btn btn-inverse action-button"  >Example</button>
</form>

Server.R

shinyServer(function(input, output, session) {

 # Create a reactiveValues object, to let us use settable reactive values
 values <- reactiveValues()
 # To start out, lastAction == NULL, meaning nothing clicked yet
 values$lastAction <- NULL
 # An observe block for each button, to record that the action happened
 observe({
  if (input$exampleFasta != 0) {
   values$lastAction <- 'example'
  }
 })
 observe({
  if (input$uploadFasta != 0) {
   values$lastAction <- 'upload'
  })
 })

 # Then you can use values$lastAction in reactive expressions, outputs, etc.
 output$table <- renderText({
  if (is.null(values$lastAction)) 
   return(NULL)
  if (identical(values$lastAction, 'upload'))
   return(myRenderTable(matrixProtein(), "table", nameFile))
  if (identical(values$lastAction, 'example'))
   return(myRenderTable(matrixProteinExample(), "table", ""))
  stop("Unexpected value for lastAction: ", values$lastAction)
 })
})

Note: Joe Cheng made the code of server.R, and I copied to work in this example to shiny Change data input of buttons

1
  • I don't understand the question, can someone edit it to be more clear? Commented Jun 24, 2015 at 16:52

2 Answers 2

5
+100

This question was made more difficult to answer without a reproducible example. However, I've put together a self-contained example and fixed it so that it works. There were two problems with the code as it stood. The first, as identified by @xiaodai (but without adequate explanation) was that the file upload element wasn't isolated from the reactive context. This meant that any time the file element was changed, the output changed also. The second issue was that the code for each button was only being called once when clicking on it multiple times in a row, which meant that uploads didn't happen (after fixing the isolate issue) if you'd failed to click on the Example button first.

Now it works as I believe the OP wanted.

Here's the fixed index.html:

<html>
  <head>
  <script src="shared/jquery.js" type="text/javascript"></script>
  <script src="shared/shiny.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="shared/shiny.css"/> 
</head>
<body>
<form class="span12 menu-med-upload">
 <div class="row-fluid">
  <h3>Upload File .fasta</h3>
  <div class="custom-input-file btn btn-inverse">
   <input type="file" size="1" name="fileFasta" id="fileFasta" class="input-file" />
   Select File
  </div>
 </div>
 <button id="uploadFasta" type="button" class="btn btn-inverse action-button" >Upload    File</button>
 <button id="exampleFasta" type="button" class="btn btn-inverse action-button"  >Example</button>
</form>
  <div id="table" class="shiny-html-output"></div>
</body>
</html>

And here's the fixed server.R:

library("xtable")
library("Biostrings")

myRenderTable <- function(data, dataType, nameFile) {
  print(xtable(data), type = "html", print.results = FALSE)
}

matrixProtein <- function(fastaFile) {
  fasta <- readDNAStringSet(fastaFile)
  alphabetFrequency(translate(fasta))
}

matrixProteinExample <- function() {
  matrixProtein(system.file("extdata", "someORF.fa", package="Biostrings"))
}

shinyServer(function(input, output, session) {

  # Create a reactiveValues object, to let us use settable reactive values
  values <- reactiveValues()
  # To start out, lastAction == NULL, meaning nothing clicked yet
  values$lastAction <- NULL
  # An observe block for each button, to record that the action happened
  # Note setting the lastAction to NULL and then to a string ensures the output
  # is generated each time the button is clicked which is necessary for the upload button
  observeEvent(input$exampleFasta, {
    values$lastAction <- "example"
  })
  observeEvent(input$uploadFasta, {
    values$lastAction <- NULL
    values$lastAction <- "upload"
  })

  nameFile <- "Random"

  # Then you can use values$lastAction in reactive expressions, outputs, etc.
  output$table <- renderText({
    if (is.null(values$lastAction)) 
      return(NULL)
    if (identical(values$lastAction, 'upload')) {
        if (!is.null(isolate(input$fileFasta))) {
          return(myRenderTable(isolate(matrixProtein(input$fileFasta$datapath)), "table", nameFile))
        } else {
          stop("No file provided")
        }
    } else if (identical(values$lastAction, 'example'))
      return(myRenderTable(matrixProteinExample(), "table", ""))
    stop("Unexpected value for lastAction: ", values$lastAction)
  })
})

Note that this depends on the Bioconductor package Biostrings and the CRAN package xtable. I've no idea what the original functions did, but this code takes a FASTA formatted file, reads in the sequences, translates to a protein sequence and then gives a table of alphabet frequency.

Also note I've no idea what the other parameters to myRenderTable meant, so I've ignored them.

Sign up to request clarification or add additional context in comments.

1 Comment

I've already somewhat solved my own problem, as I was the one that put the bounty, but it appears your answer has best solved the problem. +1.
-4

You want isolate. So type this into the R console

?shiny::isolate

1 Comment

This answer amounts to the equivalent of a link; it merely points to the R help (indeed I can give a URL with the same information). You should probably expand on your answer to explain why using isolate is an answer to the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.