Search code examples
rshinyreactive-programming

add shiny selections to table which can be exported


I have the following app which I created with some help from stack overflow

I want to be able to pick the practice for each doctor, then create a table based on the user input, then be able to export that table.

The app needs to adjust for a variable amount of doctors each time (the real app pulls from a dynamic database with new docs being added daily), hence the renderUI with conditional panels

I am having trouble passing selections from the practice into a table which I can render and export.

Any help much appreciated.

Here is my reprex

library(tidyverse)
library(shiny)

find_docs <- dplyr::tibble(record = c("joe", "mary", "dan", "suzie"))
locs_locs <- dplyr::tibble(record = c("practice1", "practice2", "practice3"))

mytable <- dplyr::tibble(
          doc = find_docs$record, 
          location = rep("", length(find_docs$record))
)

ui <- fluidPage(
          #numericInput("num_selected", label = "Fields to Display", value = 0, min = 0, max = 10, step = 1),
          uiOutput("condPanels"), 
          tableOutput(outputId = "mydt")
)

server<-function(input,output,session){
          
          
          
          output$condPanels <- renderUI({
                    # if selected value = 0 dont create a condPanel,...
                   # if(!input$num_selected) return(NULL)
                    tagList(
                              lapply(head(find_docs$record), function(nr){
                                        conditionalPanel(
                                                  condition = paste0("Find DOC", nr),
                                                  fluidRow(
                                                            column(3, 
                                                                   tags$br(),
                                                                   nr
                                                                   
                                                                   ), 
                                                            column(3, selectInput(paste0("DOC", nr), "pick loc", 
                                                                                  choices = locs_locs))
                                                  )
                                                  
                                        )
                              })
                    ) 
          })
          
          output$mydt <- renderTable({
                    #somehow i need to use mytable here

                    z <- data.frame( g = rep(input$find_docs$record[1], length(find_docs$record)))
                    z
                    
                    # i want to render a table of find_docs in one column, and the selections in a second column)
                    # then i want to be able to export the table as csv
                    
                    
          })

}

shinyApp(ui=ui, server=server)

Solution

  • I think I was able to capture your two needs. First, I took the inputs from each of the select inputs to create the table. I used lapply to pass each of the doctors to the input name. Then I combined this with the doctor list to create a data frame and a table.

    I used the package DT for the second part of your request, to be able to download. DT has an extension which has a really easy way to download files in different ways. Hopefully this helps, good luck!

    library(tidyverse)
    library(shiny)
    library(DT) #Added DT to download the table easily
    
    find_docs <- dplyr::tibble(record = c("joe", "mary", "dan", "suzie"))
    locs_locs <- dplyr::tibble(record = c("practice1", "practice2", "practice3"))
    
    mytable <- dplyr::tibble(
      doc = find_docs$record, 
      location = rep("", length(find_docs$record))
    )
    
    ui <- fluidPage(
      uiOutput("condPanels"), 
      DTOutput(outputId = "mydt")
    )
    
    server<-function(input,output,session){
      
      
      
      output$condPanels <- renderUI({
        tagList(
          lapply(head(find_docs$record), function(nr){
            conditionalPanel(
              condition = paste0("Find DOC", nr),
              fluidRow(
                column(3, 
                       tags$br(),
                       nr
                       
                ), 
                column(3, selectInput(paste0("DOC", nr), "pick loc", 
                                      choices = locs_locs))
              )
              
            )
          })
        ) 
      })
      
      output$mydt <- renderDT({
        #An error will occur without this as it's trying to pull before these inputs are rendered
        req(input[[paste0("DOC",find_docs$record[1])]]) 
        
        z<-lapply(find_docs$record, function(x){
          input[[paste0("DOC",x)]]
        }) #Grab each of the inputs 
        
        z2 <- data.frame("DOC" = find_docs$record, "LOC" = unlist(z)) #Combine into a data frame
        z2
        
      }, extensions = "Buttons", #Using the extension addon of DT to have options to download the table
      options = list(dom = 'Bfrtip',
                     buttons = c('csv')) #Download types
      )
      
    }
    
    shinyApp(ui=ui, server=server)
    

    If you didn't want to use DT, you could also put the table into a reactiveValue, and then download it using the download button. Both of these download options are visible on this other page I just realized: Shiny R - download the result of a table