Recently we are doing file upload function, the requirement is to get the file every time the file is selected and verify the type and size, and can’t use the native input button (too ugly). We know that the input onchange event is only triggered when the selected file changes. What if the same file is selected twice? How to beautify native input elements? So began the research journey.

Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Think about the UI first

Consider the first issue: the aesthetics of native Input upload tags.

This can’t be solved with styles, only hidden or special handling:

  • Set opacity to 0 and paste it to a button. So clicking that button opens the file selection box directly
  • Hide it and programmatically trigger the input click event after clicking another button (click())

Type =”file” input elementcursor:pointer;There are some special properties: mouse over the file selection box has no effect, only over the prompt text display:This makes it impossible to achieve the mouse hand effect (important!) because the elements are stacked on top of the button. If I don’t care, I can take it.

The second method has good compatibility and adopts the mode of transit:

<button>upload</button>
<input type="file" style="display:none;"/>
<script>
document.querySelector("button").addEventListener('click'.() = >{
    document.querySelector("input[type='file']").click()
})
</script>
Copy the code

Click Discover to open the file selection box normally:

How do you get the files you select each time

The main concern is how to get the selected file without changing the selected file.

So this is actually a false statement, registering an onchange event listener means that it can only be triggered when something changes, right?

Value = “”), so that the next time the file is selected, the change event will be triggered, since the same file was selected last time.

However, the test found that this was not ok, after clearing the variable file disappeared. This path will not work!

On second thought, the elementUI component is supported by their upload component:

In the picture above, I selected the same document three times in a row, and it was well supported.

So the question is how do they do it? Then grilled steak the somebody else’s source code, the element – plus/packages/components/upload/SRC/upload. There are so few lines of code in the vue:

<div :class="['el-upload', `el-upload--${listType}`]"
    tabindex="0"
    @click="handleClick"
    @keydown.self.enter.space="handleKeydown">
    / / to omit...
</div>
function handleClick() {       
    if(! props.disabled) {// Clear the file content of the input element
        inputRef.value.value = null         
        inputRef.value.click()       
    }     
}
Copy the code

So, when the user clicks on the outer button, the input value (file inside) is cleared, and then the user selects again. If the user does not click on the input, the file will remain. That makes sense.

So according to this technique, the final code is sorted as follows:

<button>upload</button>
<input type="file" style="display:none;"/>
<script>
document.querySelector("button").addEventListener('click'.() = >{
	document.querySelector("input[type='file']").value = "";
    document.querySelector("input[type='file']").click()
})
document.querySelector("input[type='file']").addEventListener('change'.(e) = >{
    console.log(e.target.files)
})
</script>
Copy the code

Effect drawing (select the same file for three consecutive times) :

The last

Thanks for reading and I hope this article was helpful to you!