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?

Gadonski
sumber

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
BrunoLM
sumber
@ 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

Wagner Leonardi
sumber
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="*/*" />
Mariusz Wiazowski
sumber
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 = ''
}
Hukum Trafalgar
sumber
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);      
})
braitsch
sumber
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;">

sumber
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"
>
Micheal C Wallas
sumber
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 :-)

MKJ
sumber
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="" />

Singkat
sumber
3

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

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

Heckmann
sumber
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.

elshnkhll
sumber
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

Pulkit Aggarwal
sumber
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
});
Nick Craver
sumber
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>

hoi ja
sumber
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

Rui Nunes
sumber
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>
Ballpin
sumber
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.

Stephanie Schellin
sumber
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.

ArifMustafa
sumber