我想创建一个输入文件对话框。使用fileInput
函数很简单。
shinyUI(pageWithSidebar(
headerPanel(""),
sidebarPanel(
fileInput("file", "Select a file")
),
mainPanel()
))
上传后,它看起来像这样:
现在,我想将inputFile
元素重置为上传前的状态。由于没有updateFileInput
之类的功能,我是一名JS / HTML新手,我无法弄清楚如何实现这一目标。 fileInput("file", "Select a file")
的代码输出如下。
<label>Select a file</label>
<input id="file" type="file" accept="text/plain"/>
<div id="file_progress" class="progress progress-striped active shiny-file-input-progress">
<div class="bar"></div>
<label></label>
</div>
有什么想法吗?
PS。我不想在这里使用反应renderUI
来重新呈现文件输入元素。我宁愿想要'更新方式'(如果有这样的话)......
答案 0 :(得分:8)
正如@Julien Navarre所指出的,这归结为修改一些HTML / CSS。朱利安展示了如何从客户端那样做。还有待展示的是如何从服务器端执行此操作。即服务器将调用客户端上的一个函数,该函数将设置输入处理程序。您可以使用闪亮的here找到关于在服务器和客户端之间传递数据的博客文章。
在服务器端,关键函数是session$sendCustomMessage
,它将在客户端调用处理函数resetFileInputHandler
。文件输入对象的id传递给处理程序。
server.R
shinyServer(function(input, output, session) {
observe({
input$btn
session$sendCustomMessage(type = "resetFileInputHandler", "file1")
})
})
现在,在客户端,我们需要注册一个处理程序函数,该函数将由服务器调用并执行Julien概述的必要更改。
<强> ui.R 强>
shinyUI(bootstrapPage(
fileInput('file1', 'Choose File'),
actionButton("btn", "Trigger server to reset file input"),
tags$script('
Shiny.addCustomMessageHandler("resetFileInputHandler", function(x) {
var id = "#" + x + "_progress"; # name of progress bar is file1_progress
var idBar = id + " .bar";
$(id).css("visibility", "hidden"); # change visibility
$(idBar).css("width", "0%"); # reset bar to 0%
});
')
))
按下按钮现在将导致服务器调用客户端的resetFileInputHandler
(当然按钮仅用于演示目的)。
您可以找到上面的代码here或像这样运行
library(shiny)
runGist("8314905")
<强>注意强>
此解决方案在方面保持不变:文档名称显示在右侧的闪亮对象
<input id="file1" type="file" class="shiny-bound-input">
没有改变。我想这意味着要深入挖掘它。欢迎提出建议。
答案 1 :(得分:5)
也许为时已晚,但如果你还需要它,
当条形图出现时,您会看到一个新的“样式”属性:
<div id="file1_progress" class="progress progress-striped shiny-file-input-progress" style="visibility: visible;">
所有与JS有关的方法是使用他的id(“file1_progress”)获取元素,并将“style”属性的参数“visibility”设置为“hidden”。
我在Gist上放了一个例子,您可以通过运行以下命令来查看它(和代码):
shiny::runGist('8306992')
希望得到这个帮助。
答案 2 :(得分:3)
以下是重置文件输入UI的两种方法(进度条和显示的名称)。第一个使用JavaScript,第二个使用renderUI。
这些例子包括&#34; Clear&#34;按钮以及可选的下拉菜单,可在选择更改时重置文件输入UI。
<强> ui.R 强>
shinyUI(bootstrapPage(
tags$head(
tags$style(".clearButton {float:right; font-size:12px;}")
),
headerPanel("Reset file input example"),
sidebarPanel(
HTML("<button id='clearFile1' class='action-button clearButton'>Clear</button>"),
fileInput('file1', NULL, width="80%"),
selectInput('uploadFormat', label = "Select upload format",
choices = c(
"Option 1" = 'f1',
"Option 2" = 'f2',
"Option 3" = 'f3'),
selected = 'f1')
),
mainPanel(
h4("Summary"),
verbatimTextOutput("summary")
),
singleton(includeScript("active.js"))
))
<强> server.R 强>
shinyServer(function(input, output, session) {
values <- reactiveValues(
file1 = NULL
)
observe({
input$clearFile1
input$uploadFormat
values$file1 <- NULL
})
observe({
values$file1 <- input$file1
})
output$summary <- renderText({
return(paste("Uploaded file: ", values$file1$name))
})
})
<强> active.js 强>
$(document).ready(function() {
/* clear file button control */
var fileControl = $("#file1");
$("#clearFile1").on("click", function () {
fileControl.replaceWith( fileControl = fileControl.clone( true ) );
$("#file1_progress").hide();
});
$("#uploadFormat").on("change", function () {
fileControl.replaceWith( fileControl = fileControl.clone( true ) );
$("#file1_progress").hide();
});
/* file input progress bar control */
$( "#file1" ).change(function() {
document.getElementById("file1_progress").setAttribute('style', "height:20px; margin-top:5px;");
});
});
与上面相同,但是(1)摆脱了active.js和相关的include语句,(2)在ui.R中取代
fileInput('file1', NULL, width="80%"),
与
uiOutput('resettableInput'),
和(3)在server.R中添加:
output$resettableInput <- renderUI({
input$clearFile1
input$uploadFormat
fileInput('file1', NULL, width="80%")
})
请注意,可以在这里的list()语句中包含多个UI元素,并且它们都将被重新呈现。请参阅here。
您可以找到这些示例here和here的代码,并按以下方式运行:
library(shiny)
shiny::runGist('0c2a98a0236f1257fd45')
shiny::runGist('bc09d77fa92457e094c8')
答案 3 :(得分:3)
对于将来需要此功能的任何人:您可以使用reset()
包中的shinyjs
功能(自0.8版开始)https://github.com/daattali/shinyjs
答案 4 :(得分:0)
不是最好的选择,但是在下面可以找到我使用的快速解决方案。
我的系统允许对数据库中的每个条目进行注释并上传文件。 因此,当用户上传并保存entryX的fileA,然后错误地传递给entryY ...如果用户单击保存按钮,则也会为entryY保存相同的文件(fileA)。为了防止这种情况,我的快速解决方案是:
保存文件后,删除 datapath ,然后保存文件,检查 datapath 是否存在;
system(paste0(“ rm”,input $ filenote $ datapath))
file.exists(input $ filenote $ datapath)
但是,如果用户确实要为条目X和条目Y保存相同的文件(文件A),则他/她必须先上传文件B,然后再上传文件A,然后单击保存...如果在删除输入后再次选择文件A $ filenote $ datapath找不到文件A。...