4

I have an input of type file that needs to be customized. I need to add an icon in the input button, change the button's name and finally hide the selected file's name. I tried different methods like using a <div> or <a> but the problem is that I need to transfer the selected file to json format. So invoking the browsing action via JavaScript is causing an error in conversion. I need to use a customizable input of type file

                    <input type="file"/>

How I need it to look

Required shape

1

3 Answers 3

10

You can achieve this with label and hiding the input.You need to of course style it properly and write a handleFile function.

 <div>
     <label onChange={handleFile} htmlFor="formId">
         <input name="" type="file" id="formId" hidden />
          <Icon>
     </label>
 </div>
Sign up to request clarification or add additional context in comments.

Comments

6

Using the HTML label tag and htmlFor property is the best solution for this.

Step 1: Create a generic component to provide you with the functionality of file input.

// UploadControl.js

const UploadControl = ({ children, value, onChange, disabled, accept }) => {
  return (
    <label htmlFor="contained-button-file" className="m-0 w-100">
      <input
        value={value}
        accept={accept}
        disabled={disabled}
        style={{ display: 'none' }}
        id="contained-button-file"
        multiple
        type="file"
        onChange={disabled ? () => {} : onChange}
      />
      {children}
    </label>
  );
};

Step 2: Use this component by wrapping your custom-styled UI.

<button className="btn-styles">
   <UploadControl onChange={handleAddBanner} accept="image/*">
     Add New Banner
   </UploadControl>
</button>

Step 3: Implement a handler to get your file.

const handleAddBanner = ({ target: { files } }) => {
  const loadedImage = files[0];
  // loadedImage will be a image file.
};

Comments

0

To avoid the need to add an id to every input, you can create this reusable component:

import {
  DetailedHTMLProps,
  FC,
  InputHTMLAttributes,
  useRef,
} from "react";

export const FileInput: FC<
  Omit<
    DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
    "ref"
  >
> = ({ children, className, ...props }) => {
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  return (
    <button
      onClick={() => {
        fileInputRef?.current?.click();
      }}
      className={className}
    >
      <input ref={fileInputRef} style={{ display: "none" }} {...props} />
      {children}
    </button>
  );
};

This is how you use it

<FileInput
  onChange={(e) => console.log(e)}
  className={"bg-blue-950 rounded border"}
>
  Style here as you like
</FileInput>

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.