Search code examples
rshinyrmysql

Storing reactive data in shiny from SQL


This is a follow up from this question:

Acessing SQL database using shiny with reactive query

I am trying to build a data frame from data fetched from an SQL database using a shiny app. Currently i am able to query the database and return one set of data. Now I would like to save that data to a data frame and then add more data from subsequent queries. Here is my code:

UI

library(markdown)

shinyUI(fluidPage(
  titlePanel("Generic grapher"),
  sidebarLayout(
    sidebarPanel(

      numericInput("wafer", label = h3("Select wafer ID:"), value = NULL),

      actionButton("do", "An action button")
      ),

      mainPanel(
        verbatimTextOutput("value"), verbatimTextOutput("que"), dataTableOutput(outputId="pos")
      )
    )
  )
)

Server:

library(RMySQL)
library(DBI)
library(sqldf)

con = dbConnect(RMySQL::MySQL(), dbname="xx", username="pete", password="xx", host="xx", port=3306)
query <-  function(...) dbGetQuery(con, ...) 

wq = data.frame()

shinyServer(function(input, output){

  d <- eventReactive(input$do, { input$wafer })

  output$value <- renderPrint({ d() }) 

  a <- reactive({ paste("Select id from wafer where wafer_id=",d(), sep="") })

  output$que <- renderPrint({ a() }) 

  wq <- reactive({  query( a() ) })

  output$pos <- renderDataTable({ wq() })  

  })

Now I am trying to use the information from these two answers to store the data from each search I do in a data frame:

Add values to a reactive table in shiny

What's the difference between Reactive Value and Reactive Expression?

New Server:

library(RMySQL)
library(DBI)
library(sqldf)

con = dbConnect(RMySQL::MySQL(), dbname="xx", username="pete", password="xx", host="xx", port=3306)
query <-  function(...) dbGetQuery(con, ...) 

wq = data.frame()

shinyServer(function(input, output){

  values <- reactiveValues()
  values$df <- data.frame()

  d <- eventReactive(input$do, { input$wafer })

  output$value <- renderPrint({ d() }) 

  a <- reactive({ paste("Select id from wafer where wafer_id=",d(), sep="") })

  output$que <- renderPrint({ a() }) 

  wq <- reactive({  query( a() ) })

  values$df <- reactive({ rbind(values$df, wq() )   }) 

  output$pos <- renderDataTable({ values$df })  

  })

However, when I do this the data table never renders within my app. I dont have an error message. Any ideas where Im going wrong? Any help appreciated!


Solution

  • I think changing

    values$df <- reactive({ rbind(values$df, wq() )   }) 
    

    in your new server.R to

    observe({
      values$df <- rbind(isolate(values$df), wq())
    })
    

    might fix your problem.

    EDIT: Here's a working example using a local connection:

    library(markdown)
    library(RMySQL)
    library(DBI)
    library(sqldf)
    
    con <- dbConnect(RSQLite::SQLite(), ":memory:")
    dbWriteTable(con, "mtcars", mtcars)
    query <-  function(...) dbGetQuery(con, ...) 
    
    wq = data.frame()
    
    ui <- shinyUI(fluidPage(
      titlePanel("Generic grapher"),
      sidebarLayout(
        sidebarPanel(
    
          numericInput("wafer", label = h3("Select number of cylinders:"),
                       value = NULL),
    
          actionButton("do", "An action button")
        ),
    
        mainPanel(
          verbatimTextOutput("value"),
          verbatimTextOutput("que"),
          verbatimTextOutput("wq_print"),
          dataTableOutput(outputId="pos")
        )
      )
    )
    )
    
    server <- shinyServer(function(input, output){
    
      values <- reactiveValues()
      values$df <- data.frame()
    
      d <- eventReactive(input$do, { input$wafer })
    
      output$value <- renderPrint({ d() }) 
    
      a <- reactive({ paste("SELECT * FROM mtcars WHERE cyl = ", d(), sep="") })
    
      output$que <- renderPrint({ a() }) 
    
      observe({
        if (!is.null(d())) {
          wq <- reactive({  query( a() ) })
    
          output$wq_print <- renderPrint({ print(str(wq())) })
    
          values$df <- rbind(isolate(values$df), wq())
        }
      })
    
      output$pos <- renderDataTable({ values$df })  
    
    })
    
    shinyApp(ui, server)
    

    The relevant changes to your original code are the !is.null(d()) condition for handling the initial NULL value of d(), and using values$df <- rbind(isolate(values$df), wq()) inside an observer. Hope this helps with fixing your code!