1

I have a problem with managing a dynamic data.frame created in my Shiny app. Problem is, since it is handled through the server.R, I can't find a way to access it, flatten it into a vector then write it after my other variables (which are all text/numeric inputs).

Working app can be accessed here : https://samtre.shinyapps.io/fichier_test/

The data.frame is generated in "5 - Entrez le détail de chaque item", when selecting a number bigger than 1 in "4 - Items à facturer".

Here is the code in the server.R that handles creating a dynamic number of inputs :

  output$item_des <- renderUI({
    numIndividuals <- as.integer(input$numIndividuals)
    lapply(1:numIndividuals, function(i) {
      textInput(inputId = paste0("item_des", i), label = paste("Description", i))
    })
  })
  output$item_qua <- renderUI({
    numIndividuals <- as.integer(input$numIndividuals)
    lapply(1:numIndividuals, function(i) {
      numericInput(inputId = paste0("item_qua", i), label = paste("Quantité", i), value = 1, min = 1)
    })
  })
  output$item_pri <- renderUI({
    numIndividuals <- as.integer(input$numIndividuals)
    lapply(1:numIndividuals, function(i) {
      textInput(inputId = paste0("item_pri", i), label = paste("Prix", i))
    })
  })

Here is the code in server.R that creates the data.frame from the above :

  output$item_tous <- renderTable({
    num <- as.integer(input$numIndividuals)

    data.frame(cbind(
    lapply(1:num, function(i) {
      input[[paste0("item_des", i)]]
    }),
    lapply(1:num, function(i) {
      input[[paste0("item_qua", i)]]
    }),
    lapply(1:num, function(i) {
      input[[paste0("item_pri", i)]]
    })        
  ))
  }, colnames = FALSE, bordered = TRUE, digits = 0)

And finally the code in server.R that writes the .csv :

  formData <- reactive({
    data <- sapply(fieldsAll, function(x) input[[x]])
    data <- t(data)
    data
  })
  saveData <- function(data) {
    fileName <- sprintf("%s.csv",
                        input$res_fac)
    write.csv(x = data, file = file.path(responsesDir, fileName),
              row.names = FALSE, quote = TRUE)
  }

Where "fieldsAll" is a list of all the inputs to be written. It is after those that I would like to write my flatten data.frame :

fieldsAll <- c("per_nom", "per_tel", "per_dep", "fac_nom", "fac_adr", "res_dat", 
               "res_heu", "res_jou", "res_qua", "res_loc", "res_fac", "numIndividuals")

I have been stuck on this problem for a long time. Original code to mimick a google form is from : https://www.r-bloggers.com/mimicking-a-google-form-with-a-shiny-app/

While original code for creating the data.frame can be found here (Christopherlovell's answer) : Create dynamic number of input elements with R/Shiny

Thanks!

1 Answers1

0

Hi your problem is that you create your data.frame with in a render statment. Thats way you can't access it later for the csv. what you want is to place the construction of the data.frame in a reactive statment something like this

item_tous_table <- reactive({
  num <- as.integer(input$numIndividuals)

  data.frame(cbind(
    lapply(1:num, function(i) {
      input[[paste0("item_des", i)]]
    }),
    lapply(1:num, function(i) {
      input[[paste0("item_qua", i)]]
    }),
    lapply(1:num, function(i) {
      input[[paste0("item_pri", i)]]
    })        
  ))
})

and then change your render statment to something like this

output$item_tous <- renderTable({
  item_tous_table()
}, colnames = FALSE, bordered = TRUE, digits = 0)

I'm insecure what you want to do in saveData but you can access the data.frame there as well with item_tous_table()

and also I think you better place the saving of the csv in an observeEvent something like this

observeEvent({
  input$submit
},{
  fileName <- sprintf("%s.csv",
                      input$res_fac)
  write.csv(x = formData() , file = file.path(responsesDir, fileName),
            row.names = FALSE, quote = TRUE)
})  

rather then in an function.

Hope this helps!!

Bertil Baron
  • 4,923
  • 1
  • 15
  • 24