New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example Request: File inputs #1989

Open
gnarf opened this Issue Oct 19, 2016 · 20 comments

Comments

@gnarf

gnarf commented Oct 19, 2016

it's really hard to google for examples of this working with the v6 api...

Are there any examples out there, can we make some official ones on the docs page?

@dmason30

This comment has been minimized.

Show comment
Hide comment
@dmason30

dmason30 Oct 19, 2016

We ended up using react-dropzone. Just put a hidden <Field ... /> with your field name and then in your dropzone component in the onDrop prop just dispatch to that field. You may need to use the HTML5 FileReaderto handle the file.

Example image upload:
`

<Field name="file" component='input' type="hidden" />

<Dropzone
    ref="dropzone"
    onDrop={(upload) => dispatch(change('FileUploadExampleForm', 'file', upload[0]))}
    multiple={false}
    accept='image/*'>
    <div>Click here select files to upload.</div>
</Dropzone>

`

dmason30 commented Oct 19, 2016

We ended up using react-dropzone. Just put a hidden <Field ... /> with your field name and then in your dropzone component in the onDrop prop just dispatch to that field. You may need to use the HTML5 FileReaderto handle the file.

Example image upload:
`

<Field name="file" component='input' type="hidden" />

<Dropzone
    ref="dropzone"
    onDrop={(upload) => dispatch(change('FileUploadExampleForm', 'file', upload[0]))}
    multiple={false}
    accept='image/*'>
    <div>Click here select files to upload.</div>
</Dropzone>

`

@gnarf

This comment has been minimized.

Show comment
Hide comment
@gnarf

gnarf Oct 19, 2016

@dmason30 seems like a pretty great example! I still think it might be worth adding some notes about working with file inputs to the documentation, even if it is a suggestion to "work with an external plugin for file uploads"

gnarf commented Oct 19, 2016

@dmason30 seems like a pretty great example! I still think it might be worth adding some notes about working with file inputs to the documentation, even if it is a suggestion to "work with an external plugin for file uploads"

@tatemz

This comment has been minimized.

Show comment
Hide comment
@tatemz

tatemz commented Oct 26, 2016

@dmason30 ... I second @gnarf

@morgante

This comment has been minimized.

Show comment
Hide comment
@morgante

morgante Nov 22, 2016

It would be good to have an explanation of how to do this without using dropzones. Often I just want the standard file upload behavior.

morgante commented Nov 22, 2016

It would be good to have an explanation of how to do this without using dropzones. Often I just want the standard file upload behavior.

@houfeng0923

This comment has been minimized.

Show comment
Hide comment
@houfeng0923

houfeng0923 Jan 21, 2017

i made a FileField demo using [react-dropzone]

/**
 * file field that supported dnd
 */
export default class FileField extends React.Component {
    
  handleDropOrClick = (acceptedFiles, rejectedFiles, e) => {
    let eventOrValue = e;
    let {input: {onChange, onBlur}} = this.props;
    if (e.type === 'drop') {
      if (acceptedFiles.length) {
        // FileList or [File]
        eventOrValue = (e.dataTransfer && e.dataTransfer.files) || acceptedFiles;
      } else {
        eventOrValue = null;
      }
    }
    onBlur(eventOrValue); // update touched
    onChange(eventOrValue); // update value
  }


  render() {
    let {input, meta: {touched, error}} = this.props;
    let {accept, multiple} = this.props;
    let selectedFile = (input && input.value && input.value[0]) || null;
    let dropzoneProps = {
      accept,
      multiple
      onDrop: this.handleDropOrClick,
    };
    return (
      <div>
        <input type='hidden' disabled {...input} />
        {selectedFile? <span>{selectedFile.name}</span> : null}
        <Dropzone {...dropzoneProps} />  
      </div>
      );
  }
}




// use 
<Field component={ FileField } name='uploadfile' accept='application/vnd.ms-excel'
/>

houfeng0923 commented Jan 21, 2017

i made a FileField demo using [react-dropzone]

/**
 * file field that supported dnd
 */
export default class FileField extends React.Component {
    
  handleDropOrClick = (acceptedFiles, rejectedFiles, e) => {
    let eventOrValue = e;
    let {input: {onChange, onBlur}} = this.props;
    if (e.type === 'drop') {
      if (acceptedFiles.length) {
        // FileList or [File]
        eventOrValue = (e.dataTransfer && e.dataTransfer.files) || acceptedFiles;
      } else {
        eventOrValue = null;
      }
    }
    onBlur(eventOrValue); // update touched
    onChange(eventOrValue); // update value
  }


  render() {
    let {input, meta: {touched, error}} = this.props;
    let {accept, multiple} = this.props;
    let selectedFile = (input && input.value && input.value[0]) || null;
    let dropzoneProps = {
      accept,
      multiple
      onDrop: this.handleDropOrClick,
    };
    return (
      <div>
        <input type='hidden' disabled {...input} />
        {selectedFile? <span>{selectedFile.name}</span> : null}
        <Dropzone {...dropzoneProps} />  
      </div>
      );
  }
}




// use 
<Field component={ FileField } name='uploadfile' accept='application/vnd.ms-excel'
/>
@AienTech

This comment has been minimized.

Show comment
Hide comment
@AienTech

AienTech Feb 4, 2017

@houfeng0923 when reaching onBlur(eventOrValue); it shows error. and after checkup, when calling handleDropOrClick there is no input passed to props... what could possibly be wrong?

AienTech commented Feb 4, 2017

@houfeng0923 when reaching onBlur(eventOrValue); it shows error. and after checkup, when calling handleDropOrClick there is no input passed to props... what could possibly be wrong?

@yokodev

This comment has been minimized.

Show comment
Hide comment
@yokodev

yokodev Feb 10, 2017

@gnarf @morgante Any doc, example of implementing this without dropzones

yokodev commented Feb 10, 2017

@gnarf @morgante Any doc, example of implementing this without dropzones

@ClementLevesque

This comment has been minimized.

Show comment
Hide comment
@ClementLevesque

ClementLevesque Feb 25, 2017

Hello,

I have the same request @yokodev, I would like to avoid using dropzone and I would love to see an example of a file upload with redux form :) Any help @erikras ? :)

ClementLevesque commented Feb 25, 2017

Hello,

I have the same request @yokodev, I would like to avoid using dropzone and I would love to see an example of a file upload with redux form :) Any help @erikras ? :)

@damonmaria

This comment has been minimized.

Show comment
Hide comment
@damonmaria

damonmaria Mar 18, 2017

This is what I ended up doing, which keeps it nice and simple:

const adaptFileEventToValue = delegate =>
  e => delegate(e.target.files[0])

const FileInput = ({
  input: {
    value: omitValue,
    onChange,
    onBlur,
    ...inputProps,
  },
  meta: omitMeta,
  ...props,
}) =>
  <input
    onChange={adaptFileEventToValue(onChange)}
    onBlur={adaptFileEventToValue(onBlur)}
    type="file"
    {...inputProps}
    {...props}
  />

And then use FileInput as the component in a Field:

      <Field
        component={FileInput}
        name="videoFile"
      />

Redux Form is pretty impressively composable.

damonmaria commented Mar 18, 2017

This is what I ended up doing, which keeps it nice and simple:

const adaptFileEventToValue = delegate =>
  e => delegate(e.target.files[0])

const FileInput = ({
  input: {
    value: omitValue,
    onChange,
    onBlur,
    ...inputProps,
  },
  meta: omitMeta,
  ...props,
}) =>
  <input
    onChange={adaptFileEventToValue(onChange)}
    onBlur={adaptFileEventToValue(onBlur)}
    type="file"
    {...inputProps}
    {...props}
  />

And then use FileInput as the component in a Field:

      <Field
        component={FileInput}
        name="videoFile"
      />

Redux Form is pretty impressively composable.

@bristoljon

This comment has been minimized.

Show comment
Hide comment
@bristoljon

bristoljon Mar 21, 2017

@damonmaria, @houfeng0923, @dmason30 - Thanks for the examples but how do you reference the file that has been selected? I can't see any reference to it in the store.

I am using redux-form/immutable in case that makes a difference..

bristoljon commented Mar 21, 2017

@damonmaria, @houfeng0923, @dmason30 - Thanks for the examples but how do you reference the file that has been selected? I can't see any reference to it in the store.

I am using redux-form/immutable in case that makes a difference..

@damonmaria

This comment has been minimized.

Show comment
Hide comment
@damonmaria

damonmaria Mar 21, 2017

@bristoljon With what I posted above you should have a File (details here) object assigned to the appropriate property in the fields provided to onSubmit. From my example above it would be:

reduxForm({
    form: 'my-form',
    onSubmit: ({ videoFile }) => {
      ...do something with videoFile here...
    },
})(...)

At the moment I use the AWS SDK to upload it to S3 at that point. The SDK accepts a File object.

damonmaria commented Mar 21, 2017

@bristoljon With what I posted above you should have a File (details here) object assigned to the appropriate property in the fields provided to onSubmit. From my example above it would be:

reduxForm({
    form: 'my-form',
    onSubmit: ({ videoFile }) => {
      ...do something with videoFile here...
    },
})(...)

At the moment I use the AWS SDK to upload it to S3 at that point. The SDK accepts a File object.

@bristoljon

This comment has been minimized.

Show comment
Hide comment
@bristoljon

bristoljon Mar 21, 2017

@damonmaria Ah yeah, cool. Sorry I'm a Redux-form newb! Cheers for the quick reply

bristoljon commented Mar 21, 2017

@damonmaria Ah yeah, cool. Sorry I'm a Redux-form newb! Cheers for the quick reply

@samuelg0rd0n

This comment has been minimized.

Show comment
Hide comment
@samuelg0rd0n

samuelg0rd0n Oct 12, 2017

@damonmaria Not working for me :-( When I click the input, it doesn't do anything.

samuelg0rd0n commented Oct 12, 2017

@damonmaria Not working for me :-( When I click the input, it doesn't do anything.

@AndreiBru

This comment has been minimized.

Show comment
Hide comment
@AndreiBru

AndreiBru Oct 13, 2017

This method worked for me:

  1. Create a field component and remove input.value ( ref: https://redux-form.com/5.2.5/#/examples/file?_k=57hmlw )
export const field_file = ({ input, type, meta: { touched, error, warning } }) => {
  delete input.value

  return (
    <div>
      <label htmlFor={input.name}>
        Choose File from your Computer
        <input {...input} type={type}/>
      </label>
    </div>
  )
}
  1. Use it like so
<form onSubmit={postFile}>
  <Field name="file" type="file" component={field_file} />
</form>

The file will be stored in the form object just like any other normal input.

  1. Send it via async POST.
const postFile = (data) => {
  let formData = new FormData()
  formData.append('File', data.file[0])

  return axios.post('http://test.url', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
    .then(res => res.data)
}

AndreiBru commented Oct 13, 2017

This method worked for me:

  1. Create a field component and remove input.value ( ref: https://redux-form.com/5.2.5/#/examples/file?_k=57hmlw )
export const field_file = ({ input, type, meta: { touched, error, warning } }) => {
  delete input.value

  return (
    <div>
      <label htmlFor={input.name}>
        Choose File from your Computer
        <input {...input} type={type}/>
      </label>
    </div>
  )
}
  1. Use it like so
<form onSubmit={postFile}>
  <Field name="file" type="file" component={field_file} />
</form>

The file will be stored in the form object just like any other normal input.

  1. Send it via async POST.
const postFile = (data) => {
  let formData = new FormData()
  formData.append('File', data.file[0])

  return axios.post('http://test.url', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
    .then(res => res.data)
}

@gustavohenke gustavohenke added docs and removed examples labels Oct 13, 2017

@barraponto

This comment has been minimized.

Show comment
Hide comment
@barraponto

barraponto commented Oct 27, 2017

Here's a compilation of solutions from this issue and #71 :
https://gist.github.com/barraponto/c370c17b2499c36a625fe1326c57ab21

@samuelg0rd0n

This comment has been minimized.

Show comment
Hide comment
@samuelg0rd0n

samuelg0rd0n Oct 27, 2017

I "solved" it by not including the file input in redux form. I realized it was actually not necessary to keep it there.

samuelg0rd0n commented Oct 27, 2017

I "solved" it by not including the file input in redux form. I realized it was actually not necessary to keep it there.

@lvian

This comment has been minimized.

Show comment
Hide comment
@lvian

lvian Nov 20, 2017

@AndreiBru Thanks, I'm using your approach and so far it seems the simplest way to implement a non dropzone file upload.

lvian commented Nov 20, 2017

@AndreiBru Thanks, I'm using your approach and so far it seems the simplest way to implement a non dropzone file upload.

@stephencarr

This comment has been minimized.

Show comment
Hide comment
@stephencarr

stephencarr Dec 20, 2017

@barraponto this actually appears to work properly, thanks. Now I need to figure out why it works where others didn't.

stephencarr commented Dec 20, 2017

@barraponto this actually appears to work properly, thanks. Now I need to figure out why it works where others didn't.

@BryceLarkin

This comment has been minimized.

Show comment
Hide comment
@BryceLarkin

BryceLarkin Jul 19, 2018

@damonmaria This worked for me, but curious as to why you took out the field.input.value prop?

BryceLarkin commented Jul 19, 2018

@damonmaria This worked for me, but curious as to why you took out the field.input.value prop?

@damonmaria

This comment has been minimized.

Show comment
Hide comment
@damonmaria

damonmaria Jul 19, 2018

@BryceLarkin Sorry. That was a while ago so I'm not sure. Must have been a reason. Is it possible to specify value to a file input as a string?

damonmaria commented Jul 19, 2018

@BryceLarkin Sorry. That was a while ago so I'm not sure. Must have been a reason. Is it possible to specify value to a file input as a string?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment