1

I am building a Shiny dashboard that will allow me to select certain data from my postgresql database. I am new to shiny and postgresql so I appreciate your input on this. I am aiming at having a dynamic input from User, say click to select a name, a type, then the location for a certain data. And that the user can select it from a 3 selectinput widgets. The process of selecting the items will allow query of the data in the database. Lets say I have 7 names, 2 types and 3 locations.. so selecting a name, then a type, then a location will give me a part of the data. This is what my initial code looks like, but it does not give me any data showing up. I checked the connection and its working, it just doesn't can not find the data I am looking for plotting and displaying so I get an empty dashboard with no table or plot. Any idea how to go about this?


library(shiny)
library(shinydashboard)
library(RColorBrewer)
library(leaflet)
library(dplyr)
library(ggplot2)
library(tidyverse)
library(fpp)
library(plotly)
library(sp)
library(RPostgreSQL)
library(DBI)
library(pool)

#####


pool <- dbPool(drv = dbDriver("PostgreSQL", max.con = 100), user = "user", password = "pswd", host = "localhost", port = 5432, dbname = "people", idleTimeout = 3600000)

##list of people names
All<-tbl(pool, "table")
All%>%group_by(name)
names_All<- dbGetQuery(pool, "SELECT name FROM table GROUP BY name") ## list of names another way
type_grouped<- dbGetQuery(pool, "SELECT type FROM table GROUP BY type")
loc_grouped<- dbGetQuery(pool, "SELECT location FROM table GROUP BY location") 

####

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "name",
        label = " name",
        choices = names_All,
        selected = 1,
      ),
      selectInput(
        inputId = "type",
        label = " type",
        choices = type_grouped,
        selected = 1,
  
      ),
      selectInput(
        inputId = "location",
        label = " location",
        choices = loc_grouped,
        selected = 1,
      )
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("graph", plotOutput("plot")),
        tabPanel("Table", dataTableOutput("table"))
      )
    )
)
)

server <- function(input, output, session) {

  selectedData <- reactive({
    req(input$name)
    req(input$type)
    req(input$location)
    query <- glue::glue_sql(
      "SELECT * FROM table
       WHERE name IN ({name*})
       AND type IN ({type*})
       AND location IN ({location*});",
      name = input$name,
      type = input$type,
      location=input$location,
      .con = pool)
    outp <- as.data.frame(dbGetQuery(pool, query))
    outp

  })

   
  output$table <- DT::renderDataTable({
    DT::datatable(  data = selectedData(),
                   options = list(pageLength = 14),
                    rownames = FALSE)
  
  
  output$plot <- renderPlot({
    ggplot( data = selectedData(), aes(x = date, y = name )) + geom_point()
  })
  
}

shinyApp(ui = ui, server = server)

App running result

second error imgae

5
  • When you state names_All<- dbGetQuery(pool, "SELECT name FROM table GROUP BY name") where is table defined? Also, you have a typo: req(inputname) should be req(input$name) Commented Dec 31, 2020 at 5:38
  • Your SQL is not correct as you have two WHERE clauses which should have raised an error. Check console for messages. Commented Dec 31, 2020 at 5:44
  • @ YBS The table is the name of my table in the database 'people' specified in pool. So I don't have to declare it as a variable. Thanks for the note on the typo, I must have accidently delete it while typing in, but its all corrected now still no data. @Parfait its also a typo I just fixed it and still no data showing. Commented Dec 31, 2020 at 6:21
  • Please edit your post with actual code and not typos. We need to see how you fixed it. Also, post any errors that output to console. Commented Dec 31, 2020 at 15:17
  • @Parfait thanks for pointing out I can edit the post. I had no idea I can do that, I fixed the typos. And re-run the code, nothing happened I get an empty table and plot. The selector choices are working though as I can see the options. But that does not change the data I want to select from the database. I attached the image in the edited post in the App running result link above. Commented Dec 31, 2020 at 15:47

1 Answer 1

1

Consider integrating a submit button to trigger processing of server code via an eventReactive call. This even helps user understand the flow of form controls and processing. Also, right now you use SQL's IN redundantly since input choices are only single values. But use multiple=TRUE argument in selectInput() to adjust that (with note to user).

User Interface

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "name",
        label = " name",
        choices = names_All,
        selected = 1
      ),
      selectInput(
        inputId = "type",
        label = " type",
        choices = type_grouped,
        selected = 1  
      ),
      selectInput(
        inputId = "location",
        label = " location",
        choices = loc_grouped,
        selected = 1
      ),
      actionButton("submit", "Submit")        # NEW SUBMIT BUTTON
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("graph", plotOutput("plot")),
        tabPanel("Table", dataTableOutput("table"))
      )
    )
  )
)

Server Function

server <- function(input, output, session) {

  name_pick <- reactive({ req(input$name) })
  type_pick <- reactive({ req(input$type) })
  location_pick <- reactive({ req(input$location) }) 

  selectedData <- eventReactive(input$submit, { # INITIATE ON submit
    query <- "SELECT *                        
              FROM table
              WHERE name = ?name
                AND type = ?type
                AND location = ?location;"

    stmt <- DBI::sqlInterpolate(pool, 
                                query,
                                name = name_pick(),
                                type = type_pick(),
                                location = location_pick())

    outp <- dbGetQuery(pool, stmt)
  })

  output$table <- DT::renderDataTable({
    DT::datatable(data = selectedData(),
                  options = list(pageLength = 14),
                  rownames = FALSE)
  })

  output$plot <- renderPlot({
    ggplot(data = selectedData(), aes(x = date, y = name )) + 
       geom_point()
  })
  
}

Also, try avoiding SELECT * and explicitly define needed table and graph columns in specific order to control output of your Shiny result. Plus, it helps with readability and maintainability of code.

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

11 Comments

Thank you Parfait. I managed to edit my code as per your comment. I can see changes happening the console when I click submit. However, I got this error, Warning: Error in eval: attempt to apply non-function. Also just double checking, I think there is a missing bracket the line below outp after }) ) I was only able to run it after adding this one. Finally, the reason I am using SELECT , is because I want all the column names , when I tried typing it in I got a syntax error. If I shall provide them all, would using *SELECT name, etc FROM table work ?
Actually there should not be an extra closing parentheses since I had an extra opening. Please try again with my edit and describe any error or undesired results not simply it worked or it did not work. Syntax error may be due to column names with spaces or special characters. Enclose such column names with double quotes using all lowercase.
I have copied your code and use it as is. I got the above error attached as image in the post. I had to adjust location = location(), to location = location_pick (), but kept the rest the same as your code. Let me know what you think.
Error derives in UI section. See edits removing unneeded commas with small server fct fix.
Thanks, I did the edits. Now I am getting this error message Error:'data' must be 2-dimensional (e.g. data frame or matrix) , where can I convert my table from the database to a data frame?
|

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.