web-dev-qa-db-ja.com

光沢のあるfileInputオブジェクトを更新するにはどうすればよいですか?

入力ファイルダイアログを作成したい。これは、fileInput関数を使用すると簡単です。

_shinyUI(pageWithSidebar(
  headerPanel(""),
  sidebarPanel(
    fileInput("file", "Select a file")  
  ),
  mainPanel()
))
_

enter image description here

アップロード後は次のようになります。 enter image description here

ここで、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を使用して、ファイル入力要素を再レンダリングしたくありません。私はむしろ「更新方法」に行きたいです(そのようなことがあれば)...

29
Mark Heckmann

@Julien Navarreが指摘したように、これは結局、いくつかのHTML/CSSを変更することになります。ジュリアンは、クライアント側からそれを行う方法を示しました。まだ示されていないのは、サーバー側からそれを行う方法です。つまりサーバーは、入力ハンドラーを元に戻すクライアント側の関数を呼び出します。 shiny 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を呼び出します(もちろん、ボタンはデモ目的のためだけです)。

上記のコードを見つけることができます ここ またはこのように実行します

library(shiny)
runGist("8314905")

注意

このソリューションでは、アスペクトは変更されません。光沢のあるオブジェクトの右側に表示されるファイル名

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

変更されません。それはもっと深く掘り下げることを意味すると思います。提案は大歓迎です。

8
Mark Heckmann

手遅れかもしれませんが、それでも必要な場合は、

バーが表示されると、新しい「スタイル」属性が表示されます。

<div id="file1_progress" class="progress progress-striped shiny-file-input-progress" style="visibility: visible;">

JSで行う必要があるのは、ID( "file1_progress")を持つ要素を取得し、 "style"属性のパラメーター "visibility"を "hidden"に設定することだけです。

Gistに例を示します。次のコマンドを実行すると、Gist(およびコード)を確認できます。

shiny::runGist('8306992')

この助けを願っています。

5
Julien Navarre

ファイル入力UIをリセットする2つの方法(プログレスバーと表示名の両方)を次に示します。 1つ目はJavaScriptを使用し、2つ目はrenderUIを使用します。

例には、「クリア」ボタンと、選択が変更されたときにファイル入力UIをリセットするオプションのドロップダウンメニューの両方が含まれています。

例1-JavaScriptを使用する

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

});

例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%")
    })

ここでlist()ステートメントに複数のUI要素を含めることができ、それらはすべて再レンダリングされることに注意してください。 ここ を参照してください。

これらの例のコードを見つけることができます ここ および ここ そしてそれらを次のように実行します:

library(shiny)
shiny::runGist('0c2a98a0236f1257fd45')
shiny::runGist('bc09d77fa92457e094c8')
4
DavidArndt

将来この機能が必要な人のために:shinyjsパッケージのreset()関数を使用できます(バージョン0.8以降) https://github.com/daattali/ shinyjs

3
DeanAttali

最良の選択肢ではありませんが、以下に私が使用する私の簡単な解決策を見つけることができます。

私のシステムでは、データベースの各エントリにコメントを付けたり、ファイルをアップロードしたりできます。したがって、ユーザーがentryX用にfileAをアップロードして保存し、entryYに渡すと、誤ってユーザーが保存ボタンをクリックすると、同じファイル(fileA)もentryY用に保存されます。ここでこれを防ぐための私の迅速な解決策:

FileAを保存した後、datapathを削除し、ファイルを保存する前にdatapathが存在するかどうかを確認します。

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

file.exists(input $ filenote $ datapath)

しかし、ユーザーが本当にentryXとentryYに同じファイル(fileA)を保存したい場合は、最初にfileBをアップロードし、次にfileAをアップロードしてから、クリックして保存する必要があります... input $ filenote $を削除した後にfileAを再度選択した場合データパスファイルが見つかりません..。

0
Cankut çubuk