read csv shiny module?

141 views
Skip to first unread message

Ignacio Martinez

unread,
Apr 20, 2016, 1:42:18 PM4/20/16
to shiny-...@googlegroups.com
I'm trying to learn how to use shiny modules. I started with a simple app that is very similar to the one in the documentation. The app ask you to check a box, then you can upload a csv file, and it will show you a table with the data:

## app.R ##
library(shiny)
library(shinydashboard)
library(shinyjs)
# Header
header <- dashboardHeader()
# Sidebar
sidebar <- dashboardSidebar(
  checkboxInput("agree", p("I read ",
                           a("the very important stuff",
                             href="http://stackoverflow.com/",
                             target="_blank")), FALSE),
  fileInput(
  "chosenfile",
  label = h4("File input"),
  accept = ".csv"
))
# Body
body <- dashboardBody(
  useShinyjs(),
  box(
    title = "Test",
    width = 12,
    solidHeader = TRUE,
    status = "warning",
    dataTableOutput('tbl')
  )
)
# ui
ui <- dashboardPage(header, sidebar, body)
# server
server <- function(input, output) {
  #Load the chosen dataset
  data <- reactive({
    dfile <-
      input$chosenfile[1, 4] # <- filename with path is the [1,4] cell in obj
    if (!is.null(dfile))
      readr::read_csv(dfile)
  })

  output$tbl <- renderDataTable(data(),
                                options = list(scrollX = TRUE,
                                               pageLength = 10,
                                               searching = FALSE))

  observe({
    if (input$agree == T) {
      # enable the download button
      shinyjs::enable("chosenfile")
    }
  })

  observe({
    if (input$agree == F) {
      # enable the download button
      shinyjs::disable("chosenfile")
    }
  })
}
#run
shinyApp(ui, server)

I want to create a module that has the check the box, upload the file part of the app.

Right now I have this:

# Module
# Module UI function
csvFileInput <- function(id, label = "CSV file") {
  # Create a namespace function using the provided id
  ns <- NS(id)
  tagList(
    checkboxInput(ns("agree"), p("I read ",
                                   a("the very important stuff",
                                     href="http://stackoverflow.com/",
                                     target="_blank"))),
    fileInput(ns("file"), label)
  )
}

# Module server function
csvFile <- function(input, output, session) {
  # The selected file, if any
  userFile <- reactive({
    # If no file is selected, don't do anything
    validate(need(input$file, message = FALSE))
    input$file
  })
  # The user's data, parsed into a data frame
  dataframe <- reactive({
    readr::read_csv(userFile()$datapath)
  })
  # We can run observers in here if we want to
  observe({
    msg <- sprintf("File %s was uploaded", userFile()$name)
    cat(msg, "\n")
  })
  # Return the reactive that yields the data frame
  return(dataframe)
}

## app.R ##
library(shiny)
library(shinydashboard)
library(shinyjs)
# Header
header <- dashboardHeader()
# Sidebar
sidebar <- dashboardSidebar(
  csvFileInput("datafile", "CSV file")
)
# Body
body <- dashboardBody(
  useShinyjs(),
  box(
    title = "Test",
    width = 12,
    solidHeader = TRUE,
    status = "warning",
    dataTableOutput("table")
  )
)
# ui
ui <- dashboardPage(header, sidebar, body)
# server
server <- function(input, output) {
  datafile <- callModule(csvFile, "datafile")

  output$table <- renderDataTable({
    datafile()
  })

}
#run
shinyApp(ui, server)

I'm not sure how to implement the the enable/disable part of the module. I tried this, but the app crashes:

# Module
# Module UI function
csvFileInput <- function(id, label = "CSV file") {
  # Create a namespace function using the provided id
  ns <- NS(id)
  tagList(
    checkboxInput(ns("agree"), p("I read ",
                                   a("the very important stuff",
                                     href="http://stackoverflow.com/",
                                     target="_blank"))),
    fileInput(ns("file"), label)
  )
}

# Module server function
csvFile <- function(input, output, session) {
  # The selected file, if any
  userFile <- reactive({
    # If no file is selected, don't do anything
    validate(need(input$file, message = FALSE))
    input$file
  })
  # The user's data, parsed into a data frame
  dataframe <- reactive({
    readr::read_csv(userFile()$datapath)
  })
  # We can run observers in here if we want to
  observe({
    msg <- sprintf("File %s was uploaded", userFile()$name)
    cat(msg, "\n")
  })
  # Return the reactive that yields the data frame
  return(dataframe)
}

diable_button <- function(input, output, session, button, agree){
  observe({
    if (agree == T) {
      # enable the download button
      shinyjs::enable(button)
    }
  })

  observe({
    if (agree == F) {
      # enable the download button
      shinyjs::disable(button)
    }
  })
}

## app.R ##
library(shiny)
library(shinydashboard)
library(shinyjs)
# Header
header <- dashboardHeader()
# Sidebar
sidebar <- dashboardSidebar(
  csvFileInput("datafile", "CSV file")
)
# Body
body <- dashboardBody(
  useShinyjs(),
  box(
    title = "Test",
    width = 12,
    solidHeader = TRUE,
    status = "warning",
    dataTableOutput("table")
  )
)
# ui
ui <- dashboardPage(header, sidebar, body)
# server
server <- function(input, output) {
  datafile <- callModule(csvFile, "datafile")

  callModule(diable_button, "datafile", 
             button = input$chosenfile, 
             agree = input$agree)

  output$table <- renderDataTable({
    datafile()
  })

}
#run
shinyApp(ui, server)

Thanks a lot for the help!

Ignacio

PS: I posted this question on stackoverflow with no luck :(





Joe Cheng

unread,
Apr 20, 2016, 2:03:21 PM4/20/16
to Ignacio Martinez, shiny-...@googlegroups.com
In the callModule(diable_button, ...) call, pass "agree = reactive(input$agree)". And in the diable_button module, use "agree()" instead of "agree". I'm in a hurry so I can't elaborate right now but if you need help figuring out why that works, let us know.

--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/shiny-discuss/CAJA1VFxAey2JJx%2Bohpwq6xfgLqoWXyF6JJx%3Drcd0F2y4QF0WwA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Ignacio Martinez

unread,
Apr 20, 2016, 2:11:52 PM4/20/16
to Joe Cheng, shiny-...@googlegroups.com
Thanks Joe. I think I implemented the two modifications you suggested, but the code crashes:

    if (agree() == T) {
      # enable the download button
      shinyjs::enable(button)
    }
  })
  
  observe({
    if (agree() == F) {
             agree = reactive(input$agree))
  
  output$table <- renderDataTable({
    datafile()
  })
  
}
#run
shinyApp(ui, server)

Warning: Error in if: argument is of length zero
Stack trace (innermost first):
    57: observerFunc [#3]
     4: <Anonymous>
     3: do.call
     2: print.shiny.appobj
     1: <Promise>
Warning: Error in if: argument is of length zero
Stack trace (innermost first):
    57: observerFunc [#10]
     4: <Anonymous>
     3: do.call
     2: print.shiny.appobj
     1: <Promise>
ERROR: [on_request_read] connection reset by peer

That said, I would love to understand the why behind the solution (no rush at all)

Thanks again!

Ignacio


Joe Cheng

unread,
Apr 20, 2016, 2:13:09 PM4/20/16
to Ignacio Martinez, shiny-...@googlegroups.com
Does "agree = reactive(req(input$agree))" help? I'll explain if it does.

Ignacio Martinez

unread,
Apr 20, 2016, 2:16:17 PM4/20/16
to Joe Cheng, shiny-...@googlegroups.com
When I add that the app runs, but the reactivity(?) does not work. That is, the button is not disable if agree() == F

Ignacio Martinez

unread,
May 22, 2016, 12:02:32 PM5/22/16
to Joe Cheng, shiny-...@googlegroups.com
I was hoping that maybe someone figured out why this is not working.

Thanks!

Ignacio
Reply all
Reply to author
Forward
0 new messages