问题
following this post: (ShinyR : Insert user inputs in a database for further use), I found a solution to my problem, strongly inspired by this shiny app (https://deanattali.com/2015/06/14/mimicking-google-form-shiny/).
I managed to get the main result I wanted (a database combining my observations and the results of the user of the app). Nonetheless I now have two new questions:
First, how is it possible when looking at my code (complete version at the end of the post). Here are the lines from the server part of the code use to extract the inputs. Two variables are created
- Udata with only the inputs from the user, which is to be saved as a single file (%s_%s.csv).
- Mdata which is the combination of the inputs (Udata) and the database (DB_Nonames), also to be saved as a single file (%s_%s_Merged.csv).
The problem is encountered here: only one file is saved (%s_%s.csv) BUT it is composed not only of the inputs from the user (Udata) but also of the complete database (DB_Nonames). The error message is that "argument "Mdata" is missing, with no default", like it doesn't exist, however it seems that somehow Udata got merged with the database while still being called Udata (even though it's not suppose to).
formData <- reactive({
Udata <- sapply(fieldsAll, function(x) input[[x]]) #fieldsAll is an array with all the fields completed by the user
Udata <- c(Udata, PSS = (input$SSS/input$SBL)) #Test to see if I can add a new field using inputs
Udata <- t(Udata) #transposition to get a line
Mdata <- rbind(DB_NoNames,Udata) #Merge of my database and the inputs from the user
})
saveData <- function(Udata,Mdata) {
fileName <- sprintf("%s_%s.csv", #First a .csv file with only the inputs from the user
humanTime(),
digest::digest(Udata)) #To get a unique fileName for each user using time of submit and values of the inputs
fileName2 <- sprintf("%s_%s_Merged.csv", #Second a .csv file with the database + the inputs
humanTime(),
digest::digest(Udata))
write.csv(x = Udata, file = file.path(responsesDir, fileName),
row.names = c(indnames))
write.csv(x = Mdata, file = file.path(responsesDir, fileName2),
row.names = c(indnames))
}
Second, after understanding this witchcraft, how could it be fixed?
Thanks a lot to all, if I'm not clear please let me know and I'll try an other explanation.
Here is the complete code (most of it comes from https://deanattali.com/2015/06/14/mimicking-google-form-shiny/ which as detailed explainations)
#############################################
DB <- read.csv2("~/filepath/DB.csv", row.names = 1, sep=",", dec=".")
DB_NoNames <- DB
rownames(DB_NoNames) <- NULL
indnames <- c(rownames(DB),"USER")
fieldsMandatory <- c("SBL", "SSS")
labelMandatory <- function(label) {
tagList(label, span("*", class = "mandatory_star")
)}
appCSS <- ".mandatory_star { color: red; }
#error { color: red; }"
fieldsAll <- c("AGE", "SBL", "SSS")
responsesDir <- file.path("~/filepath/responses")
responsesDBDir <- file.path("~/filepath/ResponsesAndDb")
epochTime <- function() {
as.integer(Sys.time())
}
humanTime <- function() format(Sys.time(), "%Y%m%d-%H%M%OS")
loadData <- function() {
files <- list.files(file.path(responsesDir), full.names = TRUE)
data <- lapply(files, read.csv, stringsAsFactors = FALSE)
data <- dplyr::rbind_all(data)
data
}
adminUsers <- c("admin")
#############################################
shinyApp(
#############################################
ui = fluidPage(
shinyjs::useShinyjs(),
shinyjs::inlineCSS(appCSS),
titlePanel("Users'data"),
uiOutput("adminPanelContainer"),
div(
id = "form",
numericInput("AGE", "Age de la ferme", value = 1, min=0),
numericInput("SBL", labelMandatory("Surface brute en légumes (ha)"), value = 1, min=0),
numericInput("SSS", labelMandatory("Surface sous serre (ha)"), value = 0.3, min=0),
actionButton("submit", "Valider", class = "btn-primary"),
shinyjs::hidden(
span(id = "submit_msg", "Submitting..."),
div(id = "error",
div(br(), tags$b("Error: "), span(id = "error_msg"))
)
)
),
shinyjs::hidden(
div(
id = "thankyou_msg",
h3("Merci, vos données ont été enregistrées avec succès. Vous pouvez maintenant utiliser l'outil ou enregistrer de nouvelles données"),
actionLink("submit_another", "Enregistrer de nouvelles données")
)
)
),
#############################################
server = function(input, output, session) {
observe({
mandatoryFilled <-
vapply(fieldsMandatory,
function(x) {
!is.null(input[[x]]) && input[[x]] != ""
},
logical(1))
mandatoryFilled <- all(mandatoryFilled)
shinyjs::toggleState(id = "submit", condition = mandatoryFilled)
})
formData <- reactive({
Udata <- sapply(fieldsAll, function(x) input[[x]])
Udata <- c(Udata, PSS = (input$SSS/input$SBL))
Udata <- t(Udata)
Mdata <- rbind(DB_NoNames,Udata)
})
saveData <- function(Udata,Mdata) {
fileName <- sprintf("%s_%s.csv",
humanTime(),
digest::digest(Udata))
fileName2 <- sprintf("%s_%s_Merged.csv",
humanTime(),
digest::digest(Udata))
write.csv(x = Udata, file = file.path(responsesDir, fileName),
row.names = c(indnames))
# write.csv(x = Mdata, file = file.path(responsesDir, fileName2),
# row.names = c(indnames))
}
# action to take when submit button is pressed
observeEvent(input$submit, {
shinyjs::disable("submit")
shinyjs::show("submit_msg")
shinyjs::hide("error")
tryCatch({
saveData(formData())
shinyjs::reset("form")
shinyjs::hide("form")
shinyjs::show("thankyou_msg")
},
error = function(err) {
shinyjs::html("error_msg", err$message)
shinyjs::show(id = "error", anim = TRUE, animType = "fade")
},
finally = {
shinyjs::enable("submit")
shinyjs::hide("submit_msg")
})
})
observeEvent(input$submit_another, {
shinyjs::show("form")
shinyjs::hide("thankyou_msg")
})
output$responsesTable <- DT::renderDataTable(
loadData(),
rownames = FALSE,
options = list(searching = FALSE, lengthChange = FALSE)
)
output$downloadBtn <- downloadHandler(
filename = function() {
sprintf("mimic-google-form_%s.csv", humanTime())
},
content = function(file) {
write.csv(loadData(), file, row.names = FALSE)
}
)
output$adminPanelContainer <- renderUI({
if (!isAdmin()) return()
wellPanel(
h2("Previous responses (only visible to admins)"),
downloadButton("downloadBtn", "Download responses"), br(), br(),
DT::dataTableOutput("responsesTable")
)
})
isAdmin <- reactive({
is.null(session$user) || session$user %in% adminUsers
})
})
来源:https://stackoverflow.com/questions/55209822/shinyr-unexpected-result-when-exporting-inputs