React-Bootstrap Form.File and bs-custom-file-input. Can't get label to change

Viewed 15537

I'm trying to get the text box label to change on my File upload. I'm using React-Bootstraps Form.File component and read that bs-custom-file-input will work. My general code is as follows

import bsCustomFileInput from "bs-custom-file-input"

then in my useEffect

useEffect(() => {bsCustomFileInput.init()}, [])

finally in my form

<Form.Group as={Row}>
     <Form.File
          type="file"
           className="custom-file-label"
           id="inputGroupFile01"
           label="Upload Boundary File"
           custom
      />
</Form.Group>

What am I doing wrong or missing? Nothing happens with my File input box after selecting the file. Or how do i troubleshoot? I inspected the HTML and the classes and id values look correct. How can I tell if the bsCustomFileInput.init() loaded or is being used?

2 Answers

Your example snippet is working on my end: https://codesandbox.io/s/lucid-swirles-2cejw?file=/src/index.js. But, it does have a z-index issue - you can take a look at styles.css in the sandbox for that.

However, I don't think you need that library for this specific requirement. You can just store the current file name in a state and control the label prop of Form.File

function App() {
  const [fileName, setFileName] = useState("Upload Boundary File");

  return (
    <>
      <Form.Group as={Row}>
        <Form.File
          type="file"
          className="custom-file-label"
          id="inputGroupFile01"
          label={fileName}
          onChange={(e) => setFileName(e.target.files[0].name)}
          custom
        />
      </Form.Group>
    </>
  );
}

Edit romantic-allen-2evjy

Based on the idea shared in the answer from user 95faf8e76605e973, I ended up with the following:

My form component:

          <Form key={`upload_${image_type}`}>
            <div key={`${image_type}`} className="mb-3">
              <Form.File
                id={`upload_${image_type}`}
                key={`upload_${image_type}`}
                label={this.state.upload_image[`${image_type}`]["label"]}
                custom
                onChange={this.FileUploadHandler.bind(this, image_type)}
              />
            </div>
          </Form>

The fileUploadHandler function invoked on change:

  FileUploadHandler = (image_type, e) => {
    if (e.target.files) {
      console.log(e.target.files);
      let file = e.target.files[0];
      if (file) {
        let current_state = this.state.upload_image;
        current_state[image_type]["label"] = file.name;
        current_state[image_type]["file"] = file;
        this.setState({ upload_image: current_state });
      }
    } else {
      console.log("Nope");
    }
  };

The state set in my class component's constructor:

export class PackageInfo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      upload_image: {
        Wallpaper: { label: "Upload File...", file: "No file selected" },
        RotationBanner: { label: "Upload File...", file: "No file selected" },
        BootBanner: { label: "Upload File...", file: "No file selected" },
        Installer: { label: "Upload File...", file: "No file selected" },
        AppPage: { label: "Upload File...", file: "No file selected" },
        Featured: { label: "Upload File...", file: "No file selected" },
        RotationBanner: { label: "Upload File...", file: "No file selected" },
        Logo: { label: "Upload File...", file: "No file selected" },
        GameTVBanner: { label: "Upload File...", file: "No file selected" },
        GameTiles: { label: "Upload File...", file: "No file selected" },
      },
    };
  }
Related