Skip to content
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

Problems with File Upload field #448

Open
prontiol opened this issue Sep 4, 2018 · 7 comments
Open

Problems with File Upload field #448

prontiol opened this issue Sep 4, 2018 · 7 comments

Comments

@prontiol
Copy link

prontiol commented Sep 4, 2018

I'm having really hard times trying to make input[type=file] play nicely with mobx-react-form.
It doesn't work out of the box and native behavior is broken.
When a file is chosen field.files property got updated, but:

  1. Native input is not updated (still shows: "No file selected")
  2. Validation of the field is not called, so the form is still rendered invalid
  3. form.values() does not contain files selected, so basically you have to implement your own method to collect all the values

Can someone provide a very simple and limited example of the form with one required input[type=file] with form validation on file selection change and collecting the data for submit without picking data from the field itself?

@Dakkers
Copy link
Contributor

Dakkers commented Nov 1, 2018

@foxhound87 can you give a regular example of a simple file upload? I tried checking out the demo repository locally but it failed on git submodule update

@prontiol did you get this to work?

@prontiol
Copy link
Author

prontiol commented Nov 2, 2018

@Dakkers Well, I made it work, but I had to implement custom form.values() method to handle the file input.
I also hid the native input and implemented my own presentation of the selected file, based on form.$('fileinput').files) property.

@Dakkers
Copy link
Contributor

Dakkers commented Nov 2, 2018

@prontiol would you be willing to share this code? I was nearly pulling my hair out yesterday, which is a shame 'cause the rest of the library is superb.

@prontiol
Copy link
Author

prontiol commented Nov 2, 2018

@Dakkers It will be too difficult to extract the working POC from the current project, as there are lots of custom code.

@Dakkers
Copy link
Contributor

Dakkers commented Nov 2, 2018

ah ok. by "custom form.values, do you mean having special handling in the onSuccess hook?

@prontiol
Copy link
Author

prontiol commented Nov 2, 2018

@Dakkers I inherited the mobx-form and overrode the values() method to handle file inputs correctly. It's kinda simple data transform.

@Dakkers
Copy link
Contributor

Dakkers commented Nov 2, 2018

for anyone that sees this in the future, this is what I ended up doing:

Rendered component

        <div>
          <input
            {...field.bind()}
            className='display-none'
            type='file'
          />
          <button
            className='btn btn-primary'
            onBlur={field.onBlur}
            onFocus={field.onFocus}
            onClick={(e) => document.getElementById(field.id).click(e)}
            type="button"
          >
            <span>{btnText}</span>
          </button>
        </div>

Form initialization

    new Form({
      fields: [
        'image',
      ],
      initials: {
        image: null,
      },
      options: {
        image: {
          validateOnChange: true
        }
      },
      validators: {
        image: ({ field }) => {
          return [
            !!field.files && field.files.length > 0,
            'Required'
          ];
        }
      },
      hooks: {
        image: {
          onDrop: (field) => {
            field.validate({ showErrors: true })
          }
        }
      },
      types: {
        image: 'file'
      }
    }, {
      hooks: {
        onSuccess: this.submitForm
      },
      options: {
        uniqueId: () => `my-super-form-${shortid.generate()}`
      }
    });

Form submission



  * submitForm (form) {
    const data = form.values();
    console.log(form.$('image'));  // <-- this has a `.files` attribute which has the file.
  }

Explanation

https://stackoverflow.com/questions/1084925/input-type-file-show-only-button

image

  • I hide the default <input> tag using display: none (it is still rendered, technically, just hidden with CSS - so it has the field's event handling)
  • I use a button that, when clicked, finds the hidden file input and triggers its onClick
    • the hidden file input has a unique ID generated by the shortid library
  • I access the file(s) I've uploaded by doing form.$('image').files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants