3

I'am using Formik for my forms in React. Everything is okay but for the file input.

The user must be able to upload a CV. The {values.cv} in Formik does indicate that there is a value in the input. However when I send it to my Laravel back-end, I get an empty array.

I want to be able to store the file in my database. Any help would be appreciated.

The Formik file input:

<label className="btn btn-info" htmlFor="cv">
    <input id="cv" name="cv" style={{display: 'none'}} type="file" onChange={(event) => {
     setFieldValue("cv", event.currentTarget.files[0]);
                                    }} />                   
   </label>

The cv input default value is : ' '

This is what is in the {values.cv} Here is the console.log of it

In my Laravel back-end I return the $request and React is logging it. This is what I see then.

cv : []

Here is a picture of my console

2 Answers 2

4

As per this post.

<input id="file" name="file" type="file" onChange={(event) => { setFieldValue("file", event.currentTarget.files[0]); }} />

You can then access all the stuff...

JSON.stringify({ 
  fileName: values.file.name, 
  type: values.file.type,
  size: `${values.file.size} bytes`
}, null, 2);
Sign up to request clarification or add additional context in comments.

Comments

3

Formik doesn't handle file upload, but there's a hack around it provided here https://github.com/jaredpalmer/formik/issues/45

import * as React from 'react';

import { AxiosRequestConfig } from 'axios';
import Image from 'components/Image';
import { Progress } from 'components/Progress';
import ToasterInstance from '../Toast/ToasterInstance';
import { axios } from 'api/axios.config';
import { toApiError } from 'utils/api';

export interface MediaUploadProps {
  id: string;
  slug: string;
  value: string;
  onChange: (field: string, mediaId: string) => void;
}

export interface MediaUploadState {
  progress: number;
  file?: File;
  error?: string;
}

export class MediaUpload extends React.Component<
  MediaUploadProps,
  MediaUploadState
> {
  state: MediaUploadState = { progress: -1 };

  handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) {
      return;
    }
    let file = e.target.files[0];
    this.setState({ file: file });

    let data = new FormData();
    data.append('file', file);

    let config: AxiosRequestConfig = {
      onUploadProgress: (p: any) => {
        this.setState({ progress: Math.round(p.loaded * 100 / p.total) });
      },
    };

    this.setState({ error: undefined, progress: 0 });

    axios.post('/v1/media?slug=' + this.props.slug, data, config).then(
      res => {
        this.setState({ error: undefined, progress: -1 });
        this.props.onChange(this.props.id, res.data.path);
      },
      err => {
        const message = toApiError(err);
        this.setState({ error: message, progress: -1 });
        ToasterInstance.show({
          message,
          iconName: 'danger',
          intent: 'danger',
        });
      }
    );
  }

  handleRemoveImage = () => {
    this.props.onChange(this.props.id, '');
  }

  render() {
    return (
      <div>
        <div>
          {this.props.value !== '' &&
            this.state.progress === -1 &&
            <Image path={this.props.value} size="lg" />}
          <div style={{ maxWidth: 144 }}>
            {this.state.progress > -1 &&
              <Progress percentage={this.state.progress} />}
          </div>
          {this.props.value &&
            <a
              style={{ marginTop: -40 }}
              className="button button--negative button--small button--secondary"
              role="button"
              onClick={this.handleRemoveImage}
            >
              Remove
            </a>}
    </div>
    <div style={{ marginTop: 10 }}>
      <label className="button button--purple button--secondary">
        Upload new picture
        <input
          className="visually-hidden"
          type="file"
          onChange={this.handleFileChange}
        />

      </label>
    </div>

  </div>
);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.