R拖放上的闪亮输入反应错误 [英] R Shiny Input Reactivity Error on Drag-and-Drop
问题描述
我目前正在使用一些自定义js创建R Shiny应用,以提供拖放功能。虽然拖放操作对于单个文件非常有效,但是当我使用ShinyJS重置它时,再次上传相同文件无法正常工作。我了解这是因为onchange函数不会在重新输入相同名称的文件时触发(无论文件内容是否已修改)
Im currently creating a R Shiny app with some custom js to provide drag and drop functionality. While the drag and drop works perfectly for a single file, when I reset it using shinyJS, uploading the same file again does not work properly. I understand that this is because the onchange function is not being triggerred with the file with the same name being re-inputted (regardless of if the file contents have been modified)
JS:
var datasets = {};
var dragOver = function(e) { e.preventDefault(); };
var dropData = function(e) {
e.preventDefault();
handleDrop(e.dataTransfer.files);
};
var removeFiles = function(e){
jQuery('#datafile').empty();
}
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;
Shiny.onInputChange("datafile", datasets);
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);
}
};
Server.R(部分用于查看文件输入):
Server.R (The part of it looking at file input):
observeEvent(input$datafile, {
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
# CLEAN FILE
name <- names(input$datafile)[1]
csvFile <- read.csv(text=input$datafile[[name]])
output$dataTable <- renderDataTable(csvFile , options = list(scrollX = '1100px') )
}
ui .R(只是相关部分):
ui.R (Just the relevant portion):
# DRAG AND DROP FILE INPUT
h3(id="data-title", "Drop Datasets"),
div(class="col-xs-12", id="drop-area", ondragover="dragOver(event)",
ondrop="dropData(event)" , onClick="fallback(event)"),
div(onClick="removeFiles(event)", actionButton(inputId="resetAutomaticInput", label="Reset Input")
我不知道如何使闪亮的值具有反应性,以触发与input $ datafile相关的事件。
I do not understand how to make my shiny values reactive to trigger the event associated with input$datafile. Any help is deeply appreciated!
推荐答案
我对此进行了研究并使用了一段时间,使其成为一个有效的示例。第一。我认为拖放功能是一个有用的示例。它也正确处理多点。也有一些有趣的javascript构造-至少对我来说。
I had a look at this and played with it for awhile, making it into a working example first. I think the drag-and-drop functionality is a useful example here. It handles multi-drop correctly too. There are some interesting javascript constructs in it too - at least to me.
为了解决这个问题,我没有使用BigDataScientist建议的随机数,而是使用了一个对其他事物也可能有用的计数。
To fix the problem, instead of a random number like BigDataScientist suggested, I just used a count which could be useful for other things too.
总共进行了以下更改:
- 将这些片段完整地整理成一个完整的Shiny工作示例并将其保存到
- 将javascript代码放入保存了Shiny代码的目录下的名为
www
的子目录中。 li> - 在UI代码中添加了
tag $ head(tag $ script(...
语句以加载该javascript。) - 在
放置区域
div
中添加了一些innerhtml文本,因此可以将其放入。 - 在javascript中添加了
dropcount
。 - 更改了html,以使
dropcount
将回显到放置区域
div。 - 更改了输出到
verbatumPrintOutput
,以便您可以在 - 在输出中添加了更多字段,因此您可以更好地看到
input $ datafile
中的内容。 - 将JS
for
循环更改为不会产生警告的内容。 - 添加了
jslint
在顶部进行注释以消除其他警告。 - 添加了一些输出字段(
inputdatafile
和rowsdatafile
),因此您可以跟踪input $ datafile
中的内容-直到我不清楚为止真正的错误是什么,但这只是我... - 稍微改变了输出中的逻辑,以使重置功能按人们可能期望的方式工作(示例代码似乎仍然不完整)
- 可能我忘了其他一些小东西。
- Completed the fragments into a complete Shiny working example and saved it to its own directory.
- Placed the javascript code into a sub-directory named
www
under the directory the Shiny code was saved. - Added a
tag$head(tag$script(...
statement in the UI code to load that javascript. - Added some innerhtml text to the
drop-area
div
so there is something to drop it into. - Added a
dropcount
to the javascript. - Changed the html so that that
dropcount
would be echoed to thedrop-area
div. - Changed the output to
verbatumPrintOutput
so you can see more of the dataframe in less area. - Added a couple more fields to the output so you could see better what was in
input$datafile
. - Changed the JS
for
loop to something that would not generate a warning. - Added a
jslint
comment up top to get rid of another warning. - Added some output fields (
inputdatafile
androwsdatafile
) so you could track what was ininput$datafile
- until I did that I was not clear what the real error was, but that is just me... - Changed the logic slightly in the output to make the reset functionality work the way one would probably expect (the example code seemed still incomplete)
- Probably a few other small things that I forgot.
这是代码:
JS:
/*jshint loopfunc:true */ // git rid of warning
var datasets = {};
var dragOver = function(e) { e.preventDefault(); };
var dropData = function(e) {
e.preventDefault();
handleDrop(e.dataTransfer.files);
};
var dropcount=0;
var removeFiles = function(e){
txt = "Drop Area "+dropcount;
jQuery('#drop-area').html(txt);
datasets = {};
Shiny.onInputChange("datafile", datasets);
};
var handleDrop = function(files) {
for (var i = 0; i<files.length; i++) {
f = files[i];
var reader = new FileReader();
reader.onload = (function(file) {
return function(e) {
datasets[file.name.toLowerCase()+'|'+dropcount] = e.target.result;
Shiny.onInputChange("datafile", datasets);
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('');
drpel = document.getElementById("drop-area");
drpel.appendChild(div);
drpel.childNodes[0] = "Drop Area "+dropcount;
};
})(f);
reader.readAsText(f);
dropcount++;
}
};
这是闪亮的东西:
library(plotly)
library(htmlwidgets)
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
tags$head(tags$script(type="text/javascript", src = "fileUp.js")),
# DRAG AND DROP FILE INPUT
h3(id="data-title", "Drop Datasets"),
div(class="col-xs-12",id="drop-area",ondragover="dragOver(event)",
ondrop="dropData(event)",onClick="fallback(event)","Drop Area"),
div(onClick="removeFiles(event)",
actionButton(inputId="resetAutomaticInput",label="Reset Input"),
verbatimTextOutput("inputdatafile"),
verbatimTextOutput("rowsdatafile"),
verbatimTextOutput("dataTable"))
))
server <- shinyServer(function(input, output) {
observeEvent(input$datafile, {
infile <- input$datafile
if (length(infile)==0) {
# User has not uploaded a file yet
return(NULL)
}
# CLEAN FILE
name <- names(input$datafile)[length(infile)]
csvFile <- reactive(
if (length(input$datafile)>0){
read.csv(text=input$datafile[[name]])
}
)
output$dataTable <- renderPrint(csvFile())
output$inputdatafile <- renderPrint(names(input$datafile))
output$rowsdatafile <- renderPrint(sapply(input$datafile,nchar))
})
})
shinyApp(ui, server)
和一个屏幕截图:
这篇关于R拖放上的闪亮输入反应错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!