Bagaimana mendeteksi tipe input = file “ubah” untuk file yang sama?


131

Saya ingin memecat suatu peristiwa ketika pengguna memilih file. Melakukannya dengan.change acara itu berfungsi jika pengguna mengubah file setiap saat.

Tapi saya ingin memecat acara jika pengguna memilih file yang sama lagi.

  1. File pilih pengguna A.jpg (peristiwa kebakaran)
  2. File pilih pengguna B.jpg (peristiwa kebakaran)
  3. File pilih pengguna B.jpg (acara tidak menyala, saya ingin memecat)

Bagaimana saya bisa melakukannya?

Jawaban:


78

Anda bisa mengelabui itu. Hapus elemen file dan tambahkan di tempat yang sama pada changeacara. Ini akan menghapus path file yang membuatnya berubah setiap saat.

Contoh di jsFiddle.

Atau Anda cukup menggunakan .prop("value", ""), lihat contoh ini di jsFiddle .

  • jQuery 1.6+ prop
  • Versi sebelumnya attr

@ Pekka: Tidak juga. Tapi dia bisa menyesuaikannya. Katakanlah dia perlu memposting file. Setelah posting dia bisa memanggil fungsi js yang akan menghapus dan menambahkan pemilih file baru. Itu bisa dilakukan.
BrunoLM

3
Ketahuilah bahwa ketika Anda menggunakan .attr("value", "")atau .val("")(seperti disarankan oleh @ wagner-leonardi di bawah) penjelajah internet akan memecat acara perubahan sementara chrome tidak
fadomire

4
karena "nilai" adalah properti dan bukan atribut input, penggunaan jQuery yang disarankan adalah.prop("value", "")
Roger Barreto

70

Jika sudah mencoba .attr("value", "") dan tidak berhasil, jangan panik (seperti yang saya lakukan)

lakukan .val("")saja, dan akan bekerja dengan baik


49

Anda cukup mengatur untuk membatalkan jalur file setiap kali pengguna mengklik kontrol. Sekarang, bahkan jika pengguna memilih file yang sama, onchange acara akan dipicu.

<input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />

2
Saya membutuhkan solusi seperti ini. Ini sangat singkat dan menyelesaikan pekerjaan. Mariusz Wiazowski berpikir bagus.
Jay Dharmendra Solanki

Solusi lain adalah mengubah nilai ketika tag input berubah. Tapi Kami tidak berharap nilainya berubah setelah memilih file.
songgeb

1
Keren, jauh lebih baik daripada menghapus dan menambahkan elemen di dom lagi, thx
David Dal Busco

24

Gunakan acara onClick untuk menghapus nilai input target, setiap kali pengguna mengklik bidang. Ini memastikan bahwa acara onChange akan dipicu untuk file yang sama juga. Bekerja untuk saya :)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

Menggunakan TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

17

Saya mendapatkan ini untuk bekerja dengan membersihkan nilai input file pada Klik dan kemudian memposting file di Ubah. Ini memungkinkan pengguna untuk memilih file yang sama dua kali berturut-turut dan masih memiliki perubahan acara untuk dikirim ke server. Contoh saya menggunakan plugin formulir jQuery .

$('input[type=file]').click(function(){
    $(this).attr("value", "");
})  
$('input[type=file]').change(function(){
    $('#my-form').ajaxSubmit(options);      
})

onClickKebakaran sebelumnya onChange, jadi metode ini sangat bagus untuk saya.
iplus26

8

Ini bekerja untuk saya

<input type="file" onchange="function();this.value=null;return false;">

1
Saya kira Anda berarti sesuatu seperti function () {this.value = null; return false; }
Jacek Pietal

7

Solusi VueJs

<input
                type="file"
                style="display: none;"
                ref="fileInput"
                accept="*"
                @change="onFilePicked"
                @click="$refs.fileInput.value=null"
>

1
Terima kasih atas jawaban variasi ini
Coisox

5

Inspirasi dari @braitsch Saya telah menggunakan yang berikut di AngularJS2 saya input-file-component

<input id="file" onclick="onClick($event) onchange="onChange($event)" type="file" accept="*/*" />

export class InputFile {

    @Input()
    file:File|Blob;

    @Output()
    fileChange = new EventEmitter();

    onClick(event) {
        event.target.value=''
    }
    onChange(e){
        let files  = e.target.files;
        if(files.length){
            this.file = files[0];
        }
        else { this.file = null}
        this.fileChange.emit(this.file);
    }
}

Di sini onClick(event)saya diselamatkan :-)


3

Mungkin hal termudah yang dapat Anda lakukan adalah mengatur nilai ke string kosong. Ini memaksanya untuk 'mengubah' file setiap kali bahkan jika file yang sama dipilih lagi.

<input type="file" value="" />


3

Inilah solusi React-y way yang menurut saya berhasil bagi saya:

onClick={event => event.target.value = null}


2

Jika Anda tidak ingin menggunakan jQuery

<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

Ini berfungsi dengan baik di Firefox, tetapi untuk Chrome Anda perlu menambahkan this.value=null;setelah peringatan.


2

Secara default, properti nilai elemen input dihapus setelah pemilihan file jika input memiliki banyak atribut. Jika Anda tidak membersihkan properti ini, maka acara "ubah" tidak akan diaktifkan jika Anda memilih file yang sama. Anda dapat mengelola perilaku ini menggunakan multipleatribut.

<!-- will be cleared -->
<input type="file" onchange="yourFunction()" multiple/>
<!-- won't be cleared -->
<input type="file" onchange="yourFunction()"/>

Referensi


1

Anda tidak dapat membuat changeapi di sini (perilaku yang benar, karena tidak ada yang berubah). Namun, Anda bisa mengikat clickjuga ... meskipun ini mungkin terlalu sering menyala ... tidak ada jalan tengah di antara keduanya.

$("#fileID").bind("click change", function() {
  //do stuff
});

Tampaknya Anda hanya mengulangi kata-katanya dan .click()tidak "memilih ulang".
BrunoLM

@ BrunoLM - Tidak, bukan ... tapi saya pikir Anda membaca bagian di mana saya mengatakan Anda tidak bisa melakukan ini, clicksedekat mungkin.
Nick Craver

1

Buat untuk input acara klik dan acara perubahan. Acara klik mengosongkan input dan acara perubahan berisi kode yang ingin Anda jalankan.

Jadi acara klik akan kosong ketika Anda mengklik tombol input (sebelum pilih file windows terbuka), karenanya acara perubahan akan selalu memicu ketika Anda memilih file.

$("#input").click(function() {
  $("#input").val("")
});

$("#input").change(function() {
  //Your code you want to execute!
});
<input id="input" type="file">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>


0

Anda dapat menggunakan form.reset()untuk menghapus input filefiles . Ini akan mengatur ulang semua bidang ke nilai default, tetapi dalam banyak kasus Anda mungkin hanya menggunakan tipe input = 'file' dalam bentuk untuk mengunggah file. Dalam solusi ini tidak perlu mengkloning elemen dan menghubungkan kembali peristiwa lagi.

Terima kasih kepada philiplehmann


0

Saya mengalami masalah yang sama, saya mencari solusi di atas tetapi mereka tidak mendapatkan penjelasan yang baik apa yang sebenarnya terjadi.

Solusi ini saya tulis https://jsfiddle.net/r2wjp6u8/ tidak melakukan banyak perubahan di pohon DOM, itu hanya mengubah nilai bidang input. Dari aspek kinerja seharusnya sedikit lebih baik.

Tautan ke biola: https://jsfiddle.net/r2wjp6u8/

<button id="btnSelectFile">Upload</button>

<!-- Not displaying the Inputfield because the design changes on each browser -->
<input type="file" id="fileInput" style="display: none;">
<p>
  Current File: <span id="currentFile"></span>
</p>
<hr>
<div class="log"></div>


<script>
// Get Logging Element
var log = document.querySelector('.log');

// Load the file input element.
var inputElement = document.getElementById('fileInput');
inputElement.addEventListener('change', currentFile);

// Add Click behavior to button
document.getElementById('btnSelectFile').addEventListener('click', selectFile);

function selectFile() {
  if (inputElement.files[0]) {
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    // Reset the Input Field
    log.innerHTML += '<p>Removing file: ' + inputElement.files[0].name + '</p>'
    inputElement.value = '';
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    log.innerHTML += '<hr>'
  }

  // Once we have a clean slide, open fiel select dialog.
  inputElement.click();
};

function currentFile() {
    // If Input Element has a file
  if (inputElement.files[0]) {
    document.getElementById('currentFile').innerHTML = inputElement.files[0].name;
  }
}

</scrip>

0

Jadi, tidak ada cara untuk 100% memastikan mereka memilih file yang sama kecuali Anda menyimpan setiap file dan membandingkannya secara terprogram.

Cara Anda berinteraksi dengan file (apa yang dilakukan JS ketika pengguna 'mengunggah' file) adalah HTML5 File API dan JS FileReader .

https://www.html5rocks.com/en/tutorials/file/dndfiles/

https://scotch.io/tutorials/use-the-html5-file-api-to-work-with-files-locally-in-the-browser

Tutorial ini menunjukkan kepada Anda cara menangkap dan membaca metadata (disimpan sebagai objek js) saat file diunggah.

Buat fungsi yang menjalankan 'onChange' yang akan membaca-> store-> membandingkan metadata dari file saat ini terhadap file sebelumnya. Kemudian Anda dapat memicu acara Anda ketika file yang diinginkan dipilih.


0

Percayalah, itu pasti akan membantu Anda!

// there I have called two `onchange event functions` due to some different scenario processing.

<input type="file" class="selectImagesHandlerDialog" 
    name="selectImagesHandlerDialog" 
    onclick="this.value=null;" accept="image/x-png,image/gif,image/jpeg" multiple 
    onchange="delegateMultipleFilesSelectionAndOpen(event); disposeMultipleFilesSelections(this);" />


// delegating multiple files select and open
var delegateMultipleFilesSelectionAndOpen = function (evt) {

  if (!evt.target.files) return;

  var selectedPhotos = evt.target.files;
  // some continuous source

};


// explicitly removing file input value memory cache
var disposeMultipleFilesSelections = function () {
  this.val = null;
};

Semoga ini bisa membantu banyak dari kalian.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.