Goal: I would like for the user to upload their own data frame, specify the columns in their data frame that provide "Name", "Longitude", and "Latitude" data, then create a table using DataTable (DT
package).
Issue: The data frame appears on the render table after the user makes the selections, but when they attempt to sort each column or interact with the data, or even change a selection for "Name", "Longitude", or "Latitude", the following error message appears on the console:
ERROR: [on_request_read] parse error
Here's my code for the ui and server pages I have (note: I am using dashboardPage for layout):
Reproducible Example
ui <- dashboardPage(
dashboardHeader(title = "Test") ,
dashboardSidebar(
sidebarMenu(
menuItem("Selections", tabName = "selections"),
menuItem("Data Table", tabName = "dataTable")
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "selections",
selectInput("mapChoice",
label = "Choose a map:",
choices = c("",
"New Map from Data Table"),
selected = ""),
conditionalPanel("input.mapChoice == 'New Map from Data Table'",
fileInput("userData",
label = "Choose CSV File",
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
uiOutput("newMapUI")
),
###############################################
# Bookmark widget
shinyURL.ui(width = "400px")
###############################################
),
tabItem(
tabName = "dataTable",
DT::dataTableOutput("table")
)
)
)
)
server <- function(input, output, session) {
############################################################
# Add in function for saving and recording urls as bookmarks
shinyURL.server(session)
############################################################
userData <- reactive({
path <- input$userData
if (is.null(path))
return (NULL)
results <- read.csv(file = path$datapath,
header = TRUE,
stringsAsFactors = FALSE)
results
})
output$newMapUI <- renderUI({
list(
# Specify the column for labeling
if (!is.null(userData())) {
selectizeInput("nameCol",
label = "Choose the column to be used for
point labels: ",
choices = c(names(userData())),
multiple = TRUE,
options = list(placeholder = 'Name',
maxItems = 1))
},
# Specify longitude column
if (!is.null(userData())) {
selectizeInput("lonCol",
label = "Choose the column containing longitude
values: ",
choices = c(names(userData())),
multiple = TRUE,
options = list(placeholder = 'Longitude',
maxItems = 1))
},
# Specify latitude column
if (!is.null(userData())) {
selectizeInput("latCol",
label = "Choose the column conatining latitude
values: ",
choices = c(names(userData())),
multiple = TRUE,
options = list(placeholder = 'Latitude',
maxItems = 1))
}
)
})
nameCol <- reactive({
as.character(input$nameCol)
})
lonCol <- reactive({
as.character(input$lonCol)
})
latCol <- reactive({
as.character(input$latCol)
})
newUserData <- reactive({
if (is.null(userData()))
return (NULL)
# Create the new data frame:
if (length(nameCol()) != 0 &&
length(lonCol()) != 0 &&
length(latCol()) != 0) {
userData <- userData()
name <- nameCol()
lonCol <- lonCol()
latCol <- latCol()
results <- data.frame(Name = userData[, name],
Longitude = userData[, lonCol],
Latitude = userData[, latCol])
results$Name <- as.character(results$Name)
results$Longitude <- as.numeric(results$Longitude)
results$Latitude <- as.numeric(results$Latitude)
}
results
})
mapData <- reactive({
data <- data.frame()
if (input$mapChoice == "New Map from Data Table") {
if (length(nameCol()) != 0 &&
length(lonCol()) != 0 &&
length(latCol() != 0)) {
data <- newUserData()
}
}
data
})
output$table <- DT::renderDataTable({
datatable(mapData(),
extensions = c('Buttons', 'FixedHeader', 'Scroller'),
options = list(dom = 'Bfrtip',
buttons = list('copy', 'print',
list(extend = 'csv',
filename = 'map data',
text = 'Download')
),
scrollX = TRUE,
pageLength = nrow(mapData()),
fixedHeader = TRUE,
deferRender = FALSE,
scrollY = 400,
scroller = FALSE,
autowidth = TRUE
)
)
}
) # End of table render
}
shinyApp(ui = ui, server = server)
Note: If I attempted to use this data for a plot, that will also not work. (Plotting the points on a map is my end goal).
Update1: For some dumb reason, this snippet app runs perfectly fine as expected, yet these lines of code are directly from my application. I will continue to update as more things occur.
Update2: After heavy searching and debugging, I finally caught the source of the error message via help of the js provided by the browser while running the app. The error is trying to use shinyURL in combination with DT and fileInput. My guess is that shinyURL is attempting to save a url, which is entirely too long for the browser, and which provides info that the user gave. In other words, it might be trying to save the fileInput data with the url info..? I'm adding the shinyURL function to the example above, so that it will provide the exact same error message I was stuck on. I don't need a solution immediately, but I am curious about what's really happening. (Lines that produce error are highlighted with ### above and below.