Semantic-UI-React: missing file upload input/button
Could not find a way to present an upload file button/input using the components provided here (great library btw!)
I’ve been using this and it seems to work well, perhaps a cleaner version could be included:
function UploadButton({label, onUpload, id}) {
let fileInput = null;
// If no id was specified, generate a random one
const uid = id || Math.random().toString(36).substring(7);
return (
<span>
<label htmlFor={uid} className="ui icon button">
<i className="upload icon"></i>
{label}
</label>
<input type="file" id={uid}
style={{display: "none"}}
onChange={() => {
onUpload(fileInput.files[0]);
}}
ref={input => {
fileInput = input;
}}
/>
</span>
);
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 17
- Comments: 18 (4 by maintainers)
I think a file button is a bit too specific, the idea you’ve used is a solution.
@strrel try this one The original is a typescript snippet
For those wishing to accomplish this, the following works:
Produces:
Note that the
Label
’sas="label"
(why is this not the default??!)htmlFor
is the magic that makes it all work: The browser natively triggers an input when its associated label is clicked. A label can be associated in 2 ways:for
(htmlFor
) attribute with a value equal to the input’sname
orid
The first does not work here because there are multiple form elements within the label; unfortunately that means relying on the second, which is not as good for accessibility and is more brittle (requires manually ensuring the input’s
name
and the label’sfor
stay synced).I used a
Button
for itscursor: pointer
(and because it fits nicely with the icon).If you really wanted to go the whole 9 yards, you’d add an onChange to the input[type=file] to track the selected files and list their names below the button within the Label (which is what the native one does).
based on @jshado1’s suggestion i came up with this component. (in typescript, but you can remove unnecessary types) I just declared the
Button
as label and removed the surrounding label. That should also solve the submit problem. Furthermore you can now treat the component as a normal semanticButton
since all props are passed through. For my purpose I also added an onSelect handler:Instead of relying on ID for this, you can use
ref
and call.click()
.This is safer as there’s no risk of ID clashes
After looking for options, this is what I finally come up with (plain React no TS)
@iad42 Thank you!
It’s rare that I come across a solution that was recently posted to an issue I’m looking for in the moment. I’m not sure how much time you just saved me, but I’m sure at the very least I gained a day in development haha. Cheers! 🥂
@jshado1 Hmm, i have it inside form group, with explicit submit button to. Maybe browser specific reaction.
I did it like this, not as fancy, but works.
Just require CSS style for cursor.
@jshado1 Dose not work properly, clicking upload icon submits form. Adding type=“button” did not helped. Adding e.preventDefault() blocks file selection menu.
There should be official guide to do this properly.