title: How to use RShiny reactiveFileReader with reactiveUI and non-existent files?
body: <p><em>How would I build a reactive UI that responds to a reactiveFileReader with varying data inputs?</em></p>
  
  <p>I'm interested in integrating a reactiveFileReader into an app that graphs groups within the data and shows selected points group by group.</p>
  
  <p><strong>Challenges:</strong></p>
  
  <ol>
  <li>Not every file I can identify from the prefix and suffix exists.</li>
  <li>There are varying number of groups per file. </li>
  </ol>
  
  <p><strong><strike>CRASHES/FAILS WHEN I</strong></p>
  
  <ol>
  <li>Attempt to open a non-existent file.</li>
  <li>Update a file (so it does detect that there was a change)</strike> </li>
  </ol>
  
  <p><strong>POTENTIAL SOLUTIONS:</strong></p>
  
  <ol>
  <li><strike>Slow down/delay the next steps after reading the data so it can re-load the data. </strike> <em>Fixed via a <code>reactive()</code> and <code>req()</code></em></li>
  <li><code>isolate()</code> the dependent UI so it only changes the # of groups the first time a file is loaded. </li>
  </ol>
  
  <p>I included mock data (and its generation), a UI, the broken server, and a working server that doesn't have the reactive file reader. </p>
  
  <p><strong>UPDATES</strong> </p>
  
  <p>The only thing left is to have the <code>renderUI</code>  'group' not reset the moment the file is reread. Normally it's a good thing, but here I don't want that. </p>
  
  <p><em>Packages</em></p>
  
  <pre><code>library(tidyr); library(dplyr); library(ggplot2); library(readr); library(stringr)
  library(shiny)
  #library(DT)
  </code></pre>
  
  <p><em>Mock Data</em></p>
  
  <pre><code>a1 &lt;- structure(list(Group = c("alpha_1", "alpha_1", "alpha_2", "alpha_2", "alpha_3", "alpha_3"), Sample = c("ps_1", "ps_2", "ps_1", "ps_2", "ps_1", "ps_2"), x = c(1, 1.1, 4, 4.1, 6.8, 7), y = c(2.1, 2, 7.3, 7, 10, 9.7)), .Names = c("Group", "Sample", "x", "y"), row.names = c(NA,-6L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = structure(list(Group = structure(list(), class = c("collector_character", "collector")),Sample = structure(list(), class = c("collector_character","collector")), x = structure(list(), class = c("collector_double", "collector")), y = structure(list(), class = c("collector_double", "collector"))), .Names = c("Group", "Sample", "x", "y")), default = structure(list(), class = c("collector_guess", "collector"))), .Names = c("cols", "default"), class = "col_spec"))
  a2 &lt;- structure(list(Group = c("alpha_6", "alpha_6", "alpha_7", "alpha_7", "alpha_9", "alpha_9", "alpha_10", "alpha_10"), Sample = c("ps_1", "ps_2", "ps_1", "ps_2", "ps_1", "ps_2", "ps_1", "ps_2"), x = c(3,3.2, 5, 5.1, 1, 1.1, 5, 5.1), y = c(8.1, 7, 3, 4, 14, 15, 4,3)), .Names = c("Group", "Sample", "x", "y"), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = structure(list(Group = structure(list(), class = c("collector_character", "collector")), Sample = structure(list(), class = c("collector_character","collector")), x = structure(list(), class = c("collector_double", "collector")), y = structure(list(), class = c("collector_double", "collector"))), .Names = c("Group", "Sample", "x", "y")), default = structure(list(), class = c("collector_guess", "collector"))), .Names = c("cols", "default"), class = "col_spec"))
  b2 &lt;- structure(list(Group = c("beta_3", "beta_3", "beta_4", "beta_4", "beta_6", "beta_6"), Sample = c("ps_1", "ps_2", "ps_1", "ps_2", "ps_1", "ps_2"), x = c(3, 3.2, 5, 5.1, 1, 1.1), y = c(8.1, 7, 3, 4, 14, 15)),.Names = c("Group", "Sample", "x", "y"), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = structure(list(Group = structure(list(), class = c("collector_character", "collector")), Sample = structure(list(), class = c("collector_character","collector")), x = structure(list(), class = c("collector_double", "collector")), y = structure(list(), class = c("collector_double", "collector"))), .Names = c("Group", "Sample", "x", "y")), default = structure(list(), class = c("collector_guess", "collector"))), .Names = c("cols", "default"), class = "col_spec"))
  b3 &lt;- structure(list(Group = c("beta_3", "beta_3", "beta_4", "beta_4", "beta_6", "beta_6"), Sample = c("ps_1", "ps_2", "ps_1", "ps_2", "ps_1", "ps_2"), x = c(3, 3.2, 5, 5.1, 1, 1.1), y = c(8.1, 7, 3, 4, 14, 15)), .Names = c("Group", "Sample", "x", "y"), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = structure(list(Group = structure(list(), class = c("collector_character", "collector")), Sample = structure(list(), class = c("collector_character","collector")), x = structure(list(), class = c("collector_double", "collector")), y = structure(list(), class = c("collector_double", "collector"))), .Names = c("Group", "Sample", "x", "y")), default = structure(list(), class = c("collector_guess", "collector"))), .Names = c("cols", "default"), class = "col_spec"))
  
  # Data export to simulate the problem
  lz_write &lt;- function(input) {
    write_csv(input, paste0(substitute(input), ".csv"))
  }
  lz_write(a1); lz_write(a2); lz_write(b2); lz_write(b3) # Messed up function for lapply...
  # rm(list = ls()) # Clean the environment
  </code></pre>
  
  <p><strong>UI</strong></p>
  
  <pre><code>ui &lt;- fluidPage(
    titlePanel("Minimal Example"),
    fluidRow(
      column(width = 2, class = "well", 
             # File selection
             HTML(paste("Which file?")),
             # Prefix:
             selectInput(inputId = "p",
                         label = "Prefix:",
                         choices = c("a", "b", "c"),  
                         selected = "a"), 
  
             # Suffix:
             numericInput(inputId = "s",
                          label = "Suffix:",
                          min = 1,
                          max = 3,
                          value = 1,
                          step = 1)), 
      column(width = 10,
             plotOutput(outputId = "scatterplot",
                        dblclick = "plot_dblclick",  # Might not be necessary, but it's not more work to include but more work to exclude
                        brush = brushOpts(id =  "plot_brush", resetOnNew = TRUE)))
      ), 
    fluidRow(
      column(width = 3,
             br(),
             uiOutput(outputId = "group_n")), 
      column(width = 9, 
             fixedRow( 
               column(width = 3,
                      HTML(paste0("Arg 1"))),
               column(width = 3,
                      HTML(paste0("Arg 2"))),
               column(width = 3,
                      uiOutput(outputId = "num_2"))
               )
      )
    ),
    fluidRow(
      br(), br(), br(), #Lets add some gaps or spacing
      DT::dataTableOutput(outputId = "Table")) # Summary table
  )  # Not sure if actually necessary for this example
  </code></pre>
  
  <p><strong>Broken Server</strong>
    It's only problem right now is that the UI resets the moment the file is re-read...</p>
  
  <pre><code>server_broken &lt;- function(input, output, session) { # Broken version
  
    #Larger subset: A Reactive Expression # May be used later...
    args &lt;- reactive({
      list(input$p, input$s)  #which file do we wish to input. This was our tag
    })
    # Reactive File-reader Subset
    path &lt;- reactive({
      paste0(input$p, input$s, ".csv")
    }) # Reactive Filename, kinda like our args... 
  
  
  
    filereader &lt;- function(input) { # The function we pass into a reactive filereader. 
      suppressWarnings(read_csv(input, col_types = cols(
        Group = col_character(),
        Sample = col_character(),
        x = col_double(),
        y = col_double())
      ))
    }
  
    ##BROKEN REACTIVE FILE READER HERE##
    data_1 &lt;- reactiveValues() # The function we use for livestream data
    observe({
      if(file.exists(path()) == TRUE) {
        fileReaderData &lt;-  reactiveFileReader(500, session, path(), filereader) 
      }  else { 
        message("This file does not exist") 
      ## OR DO I DO SOMETHING ELSE HERE??##
      }
      data_1$df &lt;- reactive({ 
       ## STOPS APP CRASHING, BUT NO LONGER REFRESHES CONSTANTLY ##
        req(fileReaderData()) 
        fileReaderData()
      })   
    }) # Honestly don't understand still
  
    data &lt;- reactive(data_1$df()) # Pulling things out just so the rest of our code can stay the same. 
  
    ## END OF BROKEN FILE READER##
    ## Reactive UI HERE##
    data_m &lt;- reactive({
      req(data()) 
      args()
      tmp &lt;- isolate(select(data(), Group))
      tmp %&gt;% distinct()
    }) # number of groups
  
    output$num_2 &lt;- renderUI({
      req(data())
      numericInput(inputId = "n",
                   label = "Group:",
                   min = 1,
                   max = length(data_m()$Group), 
                   value = 1 
      )
    }) #This is our 'reactive' numeric input for groups. This caps the max of our function based on the number of groups there are per file
  
    n &lt;- reactive(input$n) #which marker number we are dealing with. 
    ## End of reactive UI##
    data_n &lt;- reactive({
      req(data()); req(data_m())
      dt &lt;- filter(data(), Group == data_m()[[1]][input$n])
    }) 
  
  
    # Create scatterplot object the plotOutput function is expecting ----
    ranges &lt;- reactiveValues(x = NULL, y = NULL)
  
  
    output$scatterplot &lt;- renderPlot({
      validate(need(data(), "The specified file does not exist. Please try another"))
      p &lt;- as.numeric(input$p)
      plot &lt;- ggplot(data_n(), aes(x, y)) +  
        labs(title = paste0("Group ", data_n()$Group[1])) + 
        labs(x = "X vals", y = "Y vals") + 
        geom_point() + theme_bw() # I already have customized aesthetics. Removed for minimalism  
      plot + coord_cartesian(xlim = ranges$x, ylim = ranges$y, expand = TRUE) # So we see all points more readily. messes up the zoom but oh well
    })
  
    # When a double-click happens, check if there's a brush on the plot.
    # If so, zoom to the brush bounds; if not, reset the zoom.
    observeEvent(input$plot_dblclick, {
      brush &lt;- input$plot_brush
      if (!is.null(brush)) {
        ranges$x &lt;- c(brush$xmin, brush$xmax)
        ranges$y &lt;- c(brush$ymin, brush$ymax)
      } else {
        ranges$x &lt;- NULL
        ranges$y &lt;- NULL
      }
    })  
  
  
    #Creating text ----
    output$group_n &lt;- renderText({
      req(data())
      paste0("There are ", length(data_m()$Group), " groups in this file.",
             tags$br("This is Group: ", data_m()$Group[n()])
      )
    }) 
  
    #Building a table for you to visibly see points. You may need to update the DT to the github version ----
    output$Table &lt;- DT::renderDataTable({
      req(data())
      brushedPoints(data_n(), brush = input$plot_brush) %&gt;%
        select(Sample) 
    })
  
  }
  </code></pre>
  
  <p><strong>Functional Server</strong></p>
  
  <p>It has been removed since the broken one at least doesn't crash, and the problem is apparent. See previous edits for the original.</p>
  
  <p><strong>Sources consulted</strong></p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/43743596/interactive-file-input-and-reactive-reading-in-shinyapp">Interactive file input and reactive reading in shinyapp</a></li>
  <li><a href="https://github.com/rstudio/shiny/issues/167" rel="nofollow noreferrer">https://github.com/rstudio/shiny/issues/167</a> 
  
  <ul>
  <li>Looking for inspiration on <code>isolate</code> and <code>observers</code></li>
  </ul></li>
  <li><a href="https://groups.google.com/forum/#!topic/shiny-discuss/QgdUfWGsuVU" rel="nofollow noreferrer">https://groups.google.com/forum/#!topic/shiny-discuss/QgdUfWGsuVU</a> </li>
  </ul>
  
  <p><strong>Session Info</strong></p>
  
  <ul>
  <li>R version 3.4.2 (2017-09-28) </li>
  <li>Platform: x86_64-w64-mingw32/x64 (64-bit)</li>
  <li>Running under: Windows 7 x64 (build 7601) Service Pack 1</li>
  </ul>
  
  <p><strong>UPDATES</strong></p>
  
  <p>Placing a reactive within an <code>Observe()</code> stopped the app from crashing, AND it does update the files (forgot to delete some stuff). All that's left is saving the dependent UI somewhere... </p>