Search code examples
rshinyuploadreactive-programming

How to remove one data from shiny when another is uploaded


To illustrate my problem through minimal example, Let's consider the below code (which serves as fully reproducible example).

library(shiny)

ui <- fluidPage(
  fileInput("upload", NULL, accept = c(".csv", ".tsv")),
  numericInput("n", "Rows", value = 5, min = 1, step = 1),
  tableOutput("head"),
  fileInput("upload2", NULL, accept = c(".csv", ".tsv")),
  numericInput("n2", "Rows", value = 5, min = 1, step = 1),
  tableOutput("head2")
)

server <- function(input, output, session) {
  data <- reactive({
    req(input$upload)
    
    ext <- tools::file_ext(input$upload$name)
    switch(ext,
           csv = vroom::vroom(input$upload$datapath, delim = ","),
           tsv = vroom::vroom(input$upload$datapath, delim = "\t"),
           validate("Invalid file; Please upload a .csv or .tsv file")
    )
  })
  
  output$head <- renderTable({
    head(data(), input$n)
  })
  
  data2 <- reactive({
    
    req(input$upload2)
    
    ext <- tools::file_ext(input$upload2$name)
    switch(ext,
           csv = vroom::vroom(input$upload2$datapath, delim = ","),
           tsv = vroom::vroom(input$upload2$datapath, delim = "\t"),
           validate("Invalid file; Please upload a .csv or .tsv file")
    )
  })
  
  output$head2 <- renderTable({
    tail(data2(), input$n2)
  })
  
}

shinyApp(ui, server)

The app asks user to upload a dataset, then asks number of rows and displays head() of that uploaded data. If user uploads another dataset, similarly it's tail is displayed.

Now my requirement is that whenever shiny app user uploads data2 for displaying bottom rows, the data for top/head rows should be removed from environment alongwith it's head info; and vice versa.

I have tried many methods like using observeEvent, eventReactive, etc. but I am unable to do. Please suggest.


Solution

  • Maybe this is what you want:

    library(shiny)
    
    ui <- fluidPage(
      fileInput("upload", NULL, accept = c(".csv", ".tsv")),
      numericInput("n", "Rows", value = 5, min = 1, step = 1),
      tableOutput("head"),
      fileInput("upload2", NULL, accept = c(".csv", ".tsv")),
      numericInput("n2", "Rows", value = 5, min = 1, step = 1),
      tableOutput("head2")
    )
    
    server <- function(input, output, session) {
      data <- reactiveVal(NULL)
      data2 <- reactiveVal(NULL)
      
      observeEvent(input$upload, {
        ext <- tools::file_ext(input$upload$name)
        new_data <- switch(ext,
                           csv = vroom::vroom(input$upload$datapath, delim = ","),
                           tsv = vroom::vroom(input$upload$datapath, delim = "\t"),
                           validate("Invalid file; Please upload a .csv or .tsv file")
        )
        data(new_data)
        data2(NULL)  
      })
      
      observeEvent(input$upload2, {
        ext <- tools::file_ext(input$upload2$name)
        new_data <- switch(ext,
                           csv = vroom::vroom(input$upload2$datapath, delim = ","),
                           tsv = vroom::vroom(input$upload2$datapath, delim = "\t"),
                           validate("Invalid file; Please upload a .csv or .tsv file")
        )
        data2(new_data)
        data(NULL)
      })
      
      output$head <- renderTable({
        req(data())
        head(data(), input$n)
      })
      
      output$head2 <- renderTable({
        req(data2())
        tail(data2(), input$n2)
      })
    }
    
    shinyApp(ui, server)