29

我想创建一个输入文件对话框。使用该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这里使用响应式来重新渲染文件输入元素。我宁愿走'更新方式'(如果有这样的事情)......

4

5 回答 5

9

正如@Julien Navarre 指出的那样,这归结为修改一些HTML/CSS。Julien 展示了如何从客户端做到这一点。还有待展示的是如何从服务器端做到这一点。即,服务器将在客户端调用一个函数,该函数将设置回输入处理程序。您可以在此处找到有关使用闪亮在服务器和客户端之间传递数据的博客文章。

在服务器端,关键函数是session$sendCustomMessage调用resetFileInputHandler客户端的处理函数。文件输入对象的 id 被传递给处理程序。

服务器.R

shinyServer(function(input, output, session) {

  observe({
    input$btn
    session$sendCustomMessage(type = "resetFileInputHandler", "file1") 
  })

})

现在,在客户端,我们需要注册一个将由服务器调用的处理函数,并按照 Julien 的概述执行必要的更改。

用户界面

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在客户端调用 (当然该按钮仅用于演示目的)。

你可以在这里找到上面的代码或者像这样运行它

library(shiny)
runGist("8314905")

警告

此解决方案保持不变:右侧显示闪亮对象的文件名

<input id="file1" type="file" class="shiny-bound-input">

没有改变。我想这将意味着更深入地挖掘它。欢迎提出建议。

于 2014-01-08T11:05:03.043 回答
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')

希望这有帮助。

于 2014-01-07T22:14:17.923 回答
4

这里有两种重置文件输入 UI 的方法(进度条和显示的名称)。第一个使用 JavaScript,第二个使用 renderUI。

这些示例包括一个“清除”按钮以及可选的下拉菜单,该菜单在选择更改时重置文件输入UI。

示例 1 - 使用 JavaScript

用户界面

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"))
))

服务器.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))
    })

})

主动.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;");
    });

});

示例 2 - 使用 renderUI

同上,但 (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%")
    })

请注意,此处可以将多个 UI 元素包含在 list() 语句中,并且它们都将被重新渲染。见这里

您可以在此处此处找到这些示例的代码,并像这样运行它们:

library(shiny)
shiny::runGist('0c2a98a0236f1257fd45')
shiny::runGist('bc09d77fa92457e094c8')
于 2015-10-21T23:36:35.763 回答
4

For anyone who needs this functionality in the future: you can use the reset() function from the shinyjs package (since version 0.8) https://github.com/daattali/shinyjs

于 2016-11-04T01:26:23.970 回答
1

不是最好的选择,但您可以在下面找到我使用的快速解决方案。

我的系统允许对数据库中的每个条目进行评论和上传文件。因此,当用户为 entryX 上传并保存文件 A,然后传递给 entryY 时,如果用户单击保存按钮,则会错误地为 entryY 保存相同的文件 (fileA)。为了防止这种情况发生,我的快速解决方案是:

保存文件A后删除数据路径,在保存文件之前检查数据路径是否存在;

system(paste0("rm",input$filenote$datapath))

file.exists(输入$filenote$datapath)

但是如果用户真的想为entryX和entryY保存相同的文件(fileA),那么他/她必须先上传fileB,然后再上传fileA,然后单击保存...如果您在删除input$filenote$后再次选择fileA数据路径它没有找到文件A....

于 2019-03-29T13:40:37.897 回答