Home > Enterprise >  Can not make the shiny modules to communicate with each other
Can not make the shiny modules to communicate with each other

Time:07-31

I am new to shinymodule and trying to modulize this reproducible shiny framework, with no success. I am trying to have 3 different modules, that communicate with each other. Here is the reproducible app without the modules.

library(shiny)
library(datasets)

ui <- shinyUI(fluidPage(
  titlePanel("Column Plot"),
  tabsetPanel(
    tabPanel("Upload File",
             titlePanel("Uploading Files"),
             sidebarLayout(
               sidebarPanel(
                 fileInput('file1', 'Choose CSV File',
                           accept=c('text/csv', 
                                    'text/comma-separated-values,text/plain', 
                                    '.csv')),
                 

                 tags$br(),
                 checkboxInput('header', 'Header', TRUE),
                 radioButtons('sep', 'Separator',
                              c(Comma=',',
                                Semicolon=';',
                                Tab='\t'),
                              ','),
                 radioButtons('quote', 'Quote',
                              c(None='',
                                'Double Quote'='"',
                                'Single Quote'="'"),
                              '"')
                 
               ),
               mainPanel(
                 tableOutput('contents')
               )
             )
    ),
    tabPanel("First Tab",
             pageWithSidebar(
               headerPanel('My First Plot'),
               sidebarPanel(
                 
                 selectInput('xcol', 'X Variable', ""),
                 selectInput('ycol', 'Y Variable', "", selected = "")
                 
               ),
               mainPanel(
                 plotOutput('MyPlot')
               )
             )
    ),
    tabPanel("second Tab",
             sidebarLayout(
               sidebarPanel(
                 fluidRow(
                   selectInput(
                     "disp",
                     "Display",
                     choices = c(
                                 Summary = "summary",
                                 Structure = "str",
                                 dimension = "dimension"
                     ),
                     selected = " "
                     
                   )
                 )
               ),
               mainPanel(
                 verbatimTextOutput("summaryy")
               )
             )

            
             
             
             
             
             
             
             )
    
    
  )
)
)

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

  
  data <- reactive({ 
    req(input$file1) 
    
    inFile <- input$file1 
    
    df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
                   quote = input$quote)
    
    
    
    updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
                      choices = names(df), selected = names(df))
    updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
                      choices = names(df), selected = names(df)[2])
    
    return(df)
  })
  
  output$contents <- renderTable({
    data()
  })
  
  output$MyPlot <- renderPlot({
    x <- data()[, c(input$xcol, input$ycol)]
    plot(x)
    
  })
  
  
  output$summaryy <- renderPrint({
    if (input$disp == "summary"){
      return(summary(data()))
    } else if (input$disp == "str"){
      return(str(data()))
    } else if (input$disp == "dimension"){
      return(dim(data()))
    }
    
    else{
      return()
    }
  })
  
  
})

shinyApp(ui, server)

And here is my attempt at modulizing the app, with three different modules, with no success. What should I do so that the modules communicate with each other and also regarding the updateselectInput() function, since, I will have more tabset/other modules that will be dependent to the uploaded data and its variables.

data_upload_Ui <- function(id){
  
  ns <- NS(id)
  
  tabPanel("Upload File",
           titlePanel("Uploading Files"),
           sidebarLayout(
             sidebarPanel(
               fileInput(ns('file1'), 'Choose CSV File',
                         accept=c('text/csv', 
                                  'text/comma-separated-values,text/plain', 
                                  '.csv')),
               

               tags$br(),
               checkboxInput(ns('header'), 'Header', TRUE),
               radioButtons(ns('sep'), 'Separator',
                            c(Comma=',',
                              Semicolon=';',
                              Tab='\t'),
                            ','),
               radioButtons(ns('quote'), 'Quote',
                            c(None='',
                              'Double Quote'='"',
                              'Single Quote'="'"),
                            '"')
               
             ),
             mainPanel(
               tableOutput(ns('contents'))
             )
           )
  )
  
}

data_upload_Server <- function(id){
  moduleServer(id, function(input, output, session){
    
    data <- reactive({ 
      req(input$file1) 
      
      inFile <- input$file1 
      
      df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
                     quote = input$quote)
      
      
      updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
                        choices = names(df), selected = names(df))
      updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
                        choices = names(df), selected = names(df)[2])
      
      return(df)
    })
    
    output$contents <- renderTable({
      data()
    })
    
  }
    
    )
}

#########################
plot_UI <- function(id){
  
  ns <- NS(id)
  
  tabPanel("First Tab",
           pageWithSidebar(
             headerPanel('My First Plot'),
             sidebarPanel(
               
               # "Empty inputs" - they will be updated after the data is uploaded
               selectInput(ns('xcol'), 'X Variable', ""),
               selectInput(ns('ycol'), 'Y Variable', "", selected = "")
               
             ),
             mainPanel(
               plotOutput(ns('MyPlot'))
             )
           )
  )
  
}


plot_Server <- function(id){
  moduleServer(id, function(input, output, session){
    
    output$MyPlot <- renderPlot({
      x <- data()[, c(input$xcol, input$ycol)]
      plot(x)
      
    })
    
  }
    
    )
}


###############################################

info_Ui <- function(id){
  
  ns <- NS(id)
  
  tabPanel("second Tab",
           sidebarLayout(
             sidebarPanel(
               fluidRow(
                 selectInput(ns(
                   "disp"),
                   "Display",
                   choices = c(
                     Summary = "summary",
                     Structure = "str",
                     dimension = "dimension"
                   ),
                   selected = " "
                   
                 )
               )
             ),
             mainPanel(
               verbatimTextOutput(ns("summaryy"))
             )
           )
           

  )
  
  
}

info_Server <- function(id){
  moduleServer(id, function(input, output, session){
    
    output$summaryy <- renderPrint({
      if (input$disp == "summary"){
        return(summary(data()))
      } else if (input$disp == "str"){
        return(str(data()))
      } else if (input$disp == "dimension"){
        return(dim(data()))
      }
      
      else{
        return()
      }
    })
    
    
  }
    
    )
}


I wrote this simple function to run the modules, but only the first modules is working. Grateful for all the help.
####################################
run_App <- function(){
  ui <- shinyUI(fluidPage(
    titlePanel("Column Plot"),
    tabsetPanel(
      data_upload_Ui("data"),
      plot_UI("plot_1"),
      info_Ui("info")
    )
  )
    
  )
  server <- function(input, output, session){
    
    data_upload_Server("data")
    
    plot_Server("plot_1")
    
    info_Server("info")
    

  }
  shinyApp(ui, server)
}


run_App()

CodePudding user response:

From what I can see you're trying to create one module per tab. The first module will be used to upload a file and will need to "return" that file into de server in order to use it for the remaining two modules.

file upload module:

file_upload_UI <- function(id) {
  ns <- NS(id)
  tabPanel(
    "Upload File",
    titlePanel("Uploading Files"),
    sidebarLayout(
      sidebarPanel(
        fileInput(ns("file1"), "Choose CSV File",
          accept = c(
            "text/csv",
            "text/comma-separated-values,text/plain",
            ".csv"
          )
        ),
        tags$br(),
        checkboxInput(ns("header"), "Header", TRUE),
        radioButtons(
          ns("sep"),
          "Separator",
          c(
            Comma = ",",
            Semicolon = ";",
            Tab = "\t"
          ),
          ","
        ),
        radioButtons(
          ns("quote"),
          "Quote",
          c(
            None = "",
            "Double Quote" = '"',
            "Single Quote" = "'"
          ),
          '"'
        )
      ),
      mainPanel(
        tableOutput(ns("contents"))
      )
    )
  )
}

file_upload_Server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      data <- reactive({
        req(input$file1)

        inFile <- input$file1

        df <- read.csv(inFile$datapath,
          header = input$header, sep = input$sep,
          quote = input$quote
        )
        return(df)
      })

      output$contents <- renderTable({
        data()
      })

      # return data
      data
    }
  )
}

Second Page module:

first_page_UI <- function(id) {
  ns <- NS(id)
  tabPanel(
    "First Tab",
    titlePanel("My First Plot"),
    sidebarPanel(
      selectInput(ns("xcol"), "X Variable", ""),
      selectInput(ns("ycol"), "Y Variable", "", selected = "")
    ),
    mainPanel(
      plotOutput(ns("MyPlot"))
    )
  )
}

first_page_Server <- function(id, df) {
  stopifnot(is.reactive(df))
  moduleServer(
    id,
    function(input, output, session) {
      observeEvent(df(), {
        updateSelectInput(session,
          inputId = "xcol", label = "X Variable",
          choices = names(df()), selected = names(df())
        )
        updateSelectInput(session,
          inputId = "ycol", label = "Y Variable",
          choices = names(df()), selected = names(df())[2]
        )
      })

      output$MyPlot <- renderPlot({
        x <- df()[, c(input$xcol, input$ycol)]
        plot(x)
      })
    }
  )
}

Third page module:

second_page_UI <- function(id) {
  ns <- NS(id)
  tabPanel(
    "second Tab",
    sidebarLayout(
      sidebarPanel(
        fluidRow(
          selectInput(
            ns("disp"),
            "Display",
            choices = c(
              Summary = "summary",
              Structure = "str",
              dimension = "dimension"
            ),
            selected = " "
          )
        )
      ),
      mainPanel(
        verbatimTextOutput(ns("summaryy"))
      )
    )
  )
}

second_page_Server <- function(id, df) {
  moduleServer(
    id,
    function(input, output, session) {
      output$summaryy <- renderPrint({
        if (input$disp == "summary") {
          return(summary(df()))
        } else if (input$disp == "str") {
          return(str(df()))
        } else if (input$disp == "dimension") {
          return(dim(df()))
        } else {
          return()
        }
      })
    }
  )
}

APP:

Notice that file_upload_server is returning a reactive dataset that will later be used as an argument for the subsequent modules.

library(shiny)
library(datasets)

ui <- shinyUI(fluidPage(
  titlePanel("Column Plot"),
  tabsetPanel(
    file_upload_UI("upload_file"),
    first_page_UI("first_page"),
    second_page_UI("second_page")
  )
))

server <- shinyServer(function(input, output, session) {
  upload_data <- file_upload_Server("upload_file")
  first_page_Server("first_page", upload_data)
  second_page_Server("second_page", upload_data)
})

shinyApp(ui, server)

Example:

enter image description here

  • Related