Looking to incorporate drag and drop functionality into a shiny app? I've been able to successfully drag and drop data into an area and read it using JavaScript, but the challenge remains in having shiny effectively recognize the dragged data so that it can be processed on the server. Below is an example setup demonstrating this concept -- as there doesn't appear to be a built-in JavaScript function for drag-n-drop.
When executed, the application should resemble the following after dropping a dataset named "dat.csv". The objective is to store the drag-and-dropped data in a variable within input
for subsequent processing in R.
https://i.sstatic.net/9eLxS.png
ui.R
library(shiny)
ui <- shinyUI(
fluidPage(
tags$head(tags$link(rel="stylesheet", href="css/styles.css", type="text/css"),
tags$script(src="getdata.js")),
h3(id="data-title", "Drop Datasets"),
div(class="col-xs-12", id="drop-area", ondragover="dragOver(event)",
ondrop="dropData(event)"),
tableOutput('table'), # currently non-functional
## debug
div(class="col-xs-12",
tags$hr(style="border:1px solid grey;width:150%"),
tags$button(id="showData", "Show", class="btn btn-info",
onclick="printData('dat.csv')")),
div(id="data-output") # display the data
)
)
server.R
## Create a sample dataset
# write.csv(data.frame(a=1:10, b=letters[1:10]), "dat.csv", row.names=FALSE)
server <- function(input, output, session) {
output$table <- renderTable(input$data) # this variable does not exist
}
www/getdata.js
var datasets = {};
var dragOver = function(e) { e.preventDefault(); };
var dropData = function(e) {
e.preventDefault();
handleDrop(e.dataTransfer.files);
};
var handleDrop = function(files) {
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = (function(file) {
return function(e) {
datasets[file.name.toLowerCase()] = e.target.result;
var div = document.createElement("div");
var src = "https://cdn0.iconfinder.com/data/icons/office/512/e42-512.png";
div.id = "datasets";
div.innerHTML = [
"<img class='thumb' src='", src, "' title='", encodeURI(file.name),
"'/>", "<br>", file.name, "<br>"].join('');
document.getElementById("drop-area").appendChild(div);
};
})(f);
reader.readAsText(f);
}
};
// debug
var printData = function(data) {
var div = document.createElement("div");
div.innerHTML = datasets[data];
document.getElementById("data-output").appendChild(div);
};
www/css/styles.css
#data-title {
text-align:center;
}
#drop-area {
background-color:#BCED91;
border:2px solid #46523C;
border-radius:25px;
height:90px;
overflow:auto;
padding:12px;
}
#drop-area #datasets {
display:inline-block;
font-size:small;
margin-right:8px;
text-align:center;
vertical-align:top;
}
.thumb {
height:45px;
}