nour
nour

Reputation: 163

React js customizing the input of type file using CSS

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

Upvotes: 4

Views: 15479

Answers (3)

Yammine Yammine
Yammine Yammine

Reputation: 1

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>

Upvotes: 0

Haider Ali Anjum
Haider Ali Anjum

Reputation: 847

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.
};

Upvotes: 6

Damian Busz
Damian Busz

Reputation: 1848

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>

Upvotes: 10

Related Questions