Search code examples
rshinyshiny-reactivity

Using R shiny module outputs similar to functions


I am trying to achieve the following with the below code:

  1. Import.Excel.Data.UI and Import.Excel.Data.Server form the UI and Server chunks of the module which will help me input "a) Excel File Path, b) Sheet Name, c) Data Range and d) check box input". The idea is to have a dataframe as an output with each row containing the above 4 columns.
  2. Import.Excel.Data.App is where I am trying to use the output from the above module. The idea is to use the dataframe generated in the module and pass each row separately into a readXLS function. In the code, I am assigning this output through the line
ABC <- Import.Excel.Data.Server("File1")
  1. My problem: I thought i generated a dataframe in the module 1 above. However, when i try to extract the class, it turns out to be of class character and not class data.frame. I am trying to print the class through the code
   output$ABC.class <- renderText(class(ABC()))
   output$ABC.matrix <- renderPrint(ABC())

in the server section of the Import.Excel.Data.App

I am unable to figure out the error - though I am not sure if the way I assigned it (as shown in 2 above) is the correct way or not.

Any help with this is appreciated please.
Full Code below

Code for Module

library(shiny)

Import.Excel.Data.UI <- function(id){
  
   ns <- NS(id)
  
  tagList(
    actionButton(ns("AddExcelDataButton"), label = "Click Here to Add Excel Data"),
    verbatimTextOutput(ns("XLmatrix"))
  )
  
}




Import.Excel.Data.Server <- function(id){
  moduleServer(id, function(input, output, session){
    ns <- session$ns
    observeEvent(eventExpr = input$AddExcelDataButton,
                
                 insertUI(selector=paste0("#",ns("AddExcelDataButton")),
                          multiple=TRUE,
                          where = "afterEnd",
                          
                          ui = tags$hr(
                            tags$div(fileInput(inputId = ns(paste0("ExcelFile",input$AddExcelDataButton)),
                                         label = paste0("Path for File",input$AddExcelDataButton),
                                         multiple  = FALSE),
                                     style = "display:inline-block; vertical-align:top"
                                     ),#end of tags$div
                          
                             tags$div(textInput(inputId = ns(paste0("ExcelSheetName",input$AddExcelDataButton)),
                                      label = paste0("Excel Sheet Name",input$AddExcelDataButton),
                                      value = "Data"),
                                      style = "display:inline-block; vertical-align:top"
                                      ),#end of tags$div
                            
                            tags$div(textInput(inputId = ns(paste0("ExcelSheetRange",input$AddExcelDataButton)),
                                               label = paste0("Excel Sheet Range", input$AddExcelDataButton),
                                               value = "C6:AL10000"),
                                     style = "display:inline-block; vertical-align:top"
                            ),#end of tags$div
                            
                            
                            tags$div(checkboxInput(inputId = ns(paste0("ExcelFileCheck",input$AddExcelDataButton)),
                                               label = paste0("Check to Use File", input$AddExcelDataButton),
                                               value = TRUE),
                                     style = "display:inline-block; vertical-align:center"
                            )#end of tags$div
                 
                 
                 )#end of tags$hr  
                 
                 )#end of insertUI
    )#end of observeEvent
    
   
    
    XLdata <- reactive({
      for (i in 1: input$AddExcelDataButton)
      {
       temp.filepath <- input[[paste0("ExcelFile",i)]]$datapath
       temp.sheetname <- input[[paste0("ExcelSheetName",i)]]
       temp.sheetrange <- input[[paste0("ExcelSheetRange",i)]]
       temp.filecheck <- input[[paste0("ExcelFileCheck",i)]]
       row.temp <- cbind(temp.filepath, temp.sheetname, temp.sheetrange, temp.filecheck)
        
        
        
        ifelse(i<=1,
              {
                XLdata.matrix <- row.temp
              },#end of if condition in ifelse i<=1
              {
                XLdata.matrix <- rbind(XLdata.matrix, row.temp)
              } #end of else in ifelse i<=1
              )#end of ifelse brackets
        
      }#end of for-loop
      
   
      XLdata.matrix <- as.data.frame(XLdata.matrix)
      XLdata.matrix
      
    })#end of reactive for XLdata
    
    output$XLmatrix <- renderPrint(XLdata())


  })#end of module server
}

Code for App

Import.Excel.Data.App <- function(){
  ui <- fluidPage(
   Import.Excel.Data.UI("File1"),
   textOutput("ABC.class"),
   verbatimTextOutput("ABC.matrix")
  )
  
  
  server <- function(input, output, session){
    ABC <- Import.Excel.Data.Server("File1")
    output$ABC.class <- renderText(class(ABC()))
    output$ABC.matrix <- renderPrint(ABC())
  }
  
  shinyApp(ui, server)
}

Import.Excel.Data.App()

Solution

  • You were very close. You just need to return the reactive object XLdata, and use req() inside the reactive object. Try this

    Import.Excel.Data.Server <- function(id){
      moduleServer(id, function(input, output, session){
        ns <- session$ns
        observeEvent(eventExpr = input$AddExcelDataButton,
                     
                     insertUI(selector=paste0("#",ns("AddExcelDataButton")),
                              multiple=TRUE,
                              where = "afterEnd",
                              
                              ui = tags$hr(
                                tags$div(fileInput(inputId = ns(paste0("ExcelFile",input$AddExcelDataButton)),
                                                   label = paste0("Path for File",input$AddExcelDataButton),
                                                   multiple  = FALSE),
                                         style = "display:inline-block; vertical-align:top"
                                ),#end of tags$div
                                
                                tags$div(textInput(inputId = ns(paste0("ExcelSheetName",input$AddExcelDataButton)),
                                                   label = paste0("Excel Sheet Name",input$AddExcelDataButton),
                                                   value = "Data"),
                                         style = "display:inline-block; vertical-align:top"
                                ),#end of tags$div
                                
                                tags$div(textInput(inputId = ns(paste0("ExcelSheetRange",input$AddExcelDataButton)),
                                                   label = paste0("Excel Sheet Range", input$AddExcelDataButton),
                                                   value = "C6:AL10000"),
                                         style = "display:inline-block; vertical-align:top"
                                ),#end of tags$div
                                
                                
                                tags$div(checkboxInput(inputId = ns(paste0("ExcelFileCheck",input$AddExcelDataButton)),
                                                       label = paste0("Check to Use File", input$AddExcelDataButton),
                                                       value = TRUE),
                                         style = "display:inline-block; vertical-align:center"
                                )#end of tags$div
                                
                                
                              )#end of tags$hr  
                              
                     )#end of insertUI
        )#end of observeEvent
        
        XLdata <- reactive({
          req(input[[paste0("ExcelFile",input$AddExcelDataButton)]])
          for (i in 1: input$AddExcelDataButton)
          {
            temp.filepath <- input[[paste0("ExcelFile",i)]]$datapath
            temp.sheetname <- input[[paste0("ExcelSheetName",i)]]
            temp.sheetrange <- input[[paste0("ExcelSheetRange",i)]]
            temp.filecheck <- input[[paste0("ExcelFileCheck",i)]]
            row.temp <- cbind(temp.filepath, temp.sheetname, temp.sheetrange, temp.filecheck)
            
            
            
            ifelse(i<=1,
                   {
                     XLdata.matrix <- row.temp
                   },#end of if condition in ifelse i<=1
                   {
                     XLdata.matrix <- rbind(XLdata.matrix, row.temp)
                   } #end of else in ifelse i<=1
            )#end of ifelse brackets
            
          }#end of for-loop
          
          
          XLdata.matrix <- as.data.frame(XLdata.matrix)
          XLdata.matrix
          
        })#end of reactive for XLdata
        
        output$XLmatrix <- renderPrint(XLdata())
        
        return(XLdata)
        
      })#end of module server
    }