Glisser et déposer des données dans l'application brillante

Comment puis-je glisser et déposer des données dans une application brillante? Je peux glisser-déposer dans une zone et le lire avec javascript, mais je ne sais pas comment faire pour que shiny l'enregistre pour que je puisse le traiter sur le serveur. Voici un exemple de configuration -- c'est un peu long b/C Je ne pense pas qu'il y ait une fonction javascript intégrée pour gérer le drag-n-drop.

actuellement, Il devrait ressembler à celui-ci lors d'une exécution et d'un jeu de données "dat.csv " est traîné dans. Le but est d'enregistrer les données qui ont été glissées dans une variable input pour qu'il puisse être traité en R. enter image description here

interface utilisateur.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'),  # doesn't do anything now

    ## 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")  # print the data
  )
)

le serveur.R

## Make 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 doesn't 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;
}
23
demandé sur jenesaisquoi 2016-03-20 02:55:17

2 réponses

il suffit d'ajouter la ligne suivante dans le fichier js

datasets[file.name.toLowerCase()] = e.target.result;
# Add this line
Shiny.onInputChange("mydata", datasets);

alors vous pouvez utiliser input$mydata dans le code du serveur. Notez que c'est une liste, donc vous devrez itérer à travers elle (également nécessaire si vous prévoyez de laisser tomber plusieurs fichiers).

code Complet (qui affiche également plusieurs fichiers csv, notez que si vous déposez plusieurs fichiers avec le même nom, un seul sera affiché):

getdata.js (ajouter une ligne comme ci-dessus)

les styles.css (pas de modifier)

interface utilisateur.R

library(shiny)

ui <- shinyUI(
  fluidPage(
    tags$head(tags$link(rel="stylesheet", href="css/styles.css", type="text/css"),
              tags$script(src="getdata.js")),
    sidebarLayout(
      sidebarPanel(
        h3(id="data-title", "Drop Datasets"),
        div(class="col-xs-12", id="drop-area", ondragover="dragOver(event)", 
            ondrop="dropData(event)")
      ),
      mainPanel(
        uiOutput('tables')
      )
    )

  )
)

le serveur.R

server <- function(input, output, session) {
  observeEvent(input$mydata, {
    len = length(input$mydata)
    output$tables <- renderUI({
      table_list <- lapply(1:len, function(i) {
        tableName <- names(input$mydata)[[i]]
        tableOutput(tableName)
      })
      do.call(tagList, table_list)
    })
    for (name in names(input$mydata)) {
      output[[name]] <- renderTable(read.csv(text=input$mydata[[name]]))
    }
  })
}
16
répondu Xiongbing Jin 2016-03-20 03:24:25

depuis août 2017 cette fonctionnalité est maintenant fournie par fileInput directement à partir de shiny! Comment merveilleux.

voici le blogpost annonçant la fonctionnalitéhttps://blog.rstudio.com/2017/08/15/shiny-1-0-4/

4
répondu Martin John Hadley 2017-12-14 14:01:00