GuerillaRadio
GuerillaRadio

Reputation: 1297

React - Manually trigger onChange event on <input type="file">

I need to manually trigger the onChange event on an <input type="file"> element after the user clicks on a reset button. I have a complex form which contains over 20 inputs and allows for dynamically adding new inputs, the handling of which is tackled by a top-level function in my container component (not shown) which accepts the change event of each input and figures out how to alter my state.

On page load I make a call to an API and pre-populate the form with data. Depending on the content queried this can sometimes include a hero image. If an image exists I display it with a 'Click to remove/change' button. Clicking on this should trigger the onChange event on the input which trickles up the React tree and updates my 'content' state (in this case removing the data in the hero_image object).

I have tried setting the value to null but because the value is already null on page load it doesn't appear to fire the onChange event. I have also tried manually triggering the event in different ways. As you are not able to pre-populate the value of a file input in the same way you would do a text input for security reasons I am struggling to figure out the best way to tackle this problem.

export default class ImageUpload extends Component {
  handleImageChange(e) {
    console.log('change');
    this.props.onChange(e);
  }

  removeImage = (e) => {
    e.preventDefault();
    // Setting the value to null doesn't trigger the onChange event
    this.inputElement.value = null;
    // Below is an attempt to manually trigger the onChange event using the input ref
    const changeEvent = new Event('change');
    this.inputElement.dispatchEvent(changeEvent);
  }

  render() {
    const { name, label, value, children, error } = this.props;

    return (
      <div>
        {label &&
          <label htmlFor={name}>{label}</label>
        }

        {children}

        <div className="image-upload-preview">
          <Button onClick={e => this.removeImage(e)}>Click to remove/change</Button>
          <img alt="" src={value.data.src} />
        </div>

        <button className="form-control image-upload-btn" onClick={this.fakeButtonClick}>
          <IconWithText text="Click to add an image from your device (JPEG, PNG, GIF)" iconName="insert-image" iconSize="M" iconFill="dark" />
          <input
            id="eugh"
            type="file"
            name={name}
            ref={(input) => { this.inputElement = input; }}
            accept="image/jpeg, image/png, image/gif"
            onChange={e => this.handleImageChange(e)}
            onClick={e => e.stopPropagation()}
          />
        </button>
      </div>
    );
  }
}

Upvotes: 2

Views: 6719

Answers (1)

nanobar
nanobar

Reputation: 66355

In your onChange you should be saving the filename to state (e.target.value I believe) and setting that to the value props of the input. If another file is chosen it will then trigger the onChange. Then on reset button if you change the state to null, does it not trigger an onChange event?

i.e.

state = {
  filename: '',
}

<input value={this.state.filename} ... />

handleImageChange(e) {
  this.setState({ filename: e.target.value });
}

handleFormReset() {
  this.setState({ filename: '' });
}

Upvotes: 1

Related Questions