0

I am building a Laravel+Vue.js SPA (Single Page Application) with BootstrapVue, VeeValidate and axios as the HTTP client.

Inside axios, when I use multipart/form-data; boundary=${uploadForm._boundary} as the Content-Type in headers then all the validations in Laravel Controller method fail.

But if I use 'content-type': 'multipart/form-data' in header then validation works except the file input field. The file field becomes empty in Laravel controller method.

This happens within the component EditProfile.vue. The content there is :

<template>
    <ValidationObserver ref="form" v-slot="{ passes }">

        <div id="registration_form">

            <div id="form_title" class="text-center">Edit Your Profile</div>
            <div v-html="result" class="result text-center"></div>

            <b-form name="uploadForm" @submit.prevent="passes(onSubmit)" @reset="resetForm"  enctype="multipart/form-data">

                <ValidationProvider vid="name" rules="required|min:2" name="name" v-slot="{ valid, errors }">
                    <b-form-group
                            label="User Name:"
                            label-for="exampleInput1"
                    >
                        <b-form-input
                                type="text"
                                disable-leading-trailing-space
                                v-model="name"
                                plaintext
                                :state="errors[0] ? false : (valid ? true : null)"
                                placeholder="Enter your name"
                        ></b-form-input>
                        <b-form-invalid-feedback id="inputLiveFeedback">{{ errors[0] }}</b-form-invalid-feedback>
                    </b-form-group>
                </ValidationProvider>


                <ValidationProvider vid="photo" rules="required" name="photo" v-slot="{ valid, errors }">
                    <b-form-group
                            label="Photo:"
                            label-for="exampleInput1"
                    >

                        <b-form-file
                            accept="image/x-png,image/gif,image/jpeg"
                            v-model="file"
                            :state="Boolean(file)"
                            placeholder="Choose a file or drop it here..."
                            drop-placeholder="Drop file here..."
                            @change="onFileChange" enctype="multipart/form-data"
                        ></b-form-file>
                        <b-form-invalid-feedback id="inputLiveFeedback">{{ errors[0] }}</b-form-invalid-feedback>
                        <div class="mt-3">Selected file: {{ file ? file.name : '' }}</div>

                        <!-- Plain mode -->
                        <!--<b-form-file v-model="file2" class="mt-3" plain></b-form-file>
                        <div class="mt-3">Selected file: {{ file2 ? file2.name : '' }}</div>-->

                        <div id="preview">
                            <img v-if="url" :src="url" />
                        </div>

                    </b-form-group>
                </ValidationProvider>

                <b-button type="submit" variant="primary">Submit</b-button>
                <b-button type="reset" variant="danger">Reset</b-button>
            </b-form>

        </div><!-- end of id registration_form-->
    </ValidationObserver>
</template>

In JS part, I have :

<script>

    import { ValidationObserver, ValidationProvider } from "vee-validate";

     export default {
        name: "EditProfile",
        props: {

        },

        components: {
            ValidationObserver,
            ValidationProvider
        },
        data: () => ({

            name: "",
            photo:"",
            file:"",
            url:"",  
            result:''

        }),

        methods: {
            onFileChange(e) {
                this.file = e.target.files[0];
                this.url = URL.createObjectURL(this.file);
            },

            onSubmit() {
                console.log("Form submitted yay!");

                this.result='<span class="wait">Please wait ...</span>';

                axios.post('/update_profile_now',
                    {
                       name: this.name,
                       photo:this.file

                    }, // the data to post
                    {

                        headers: {
      
                            //Accept: 'application/json',

                           'Content-Type':  `multipart/form-data; boundary=${uploadForm._boundary}`
                            
                        }

                    })
                    .then(response => {
      
                        if(response.data.success){

                            this.result='<span class="succes">Registration completed !!</span>';
                        } else {

                            this.$refs.form.setErrors(response.data.errors);

                            this.result='<span class="error">Invalid data !!</span>';
                        }

                    })
                    .catch(error => {

                        if(typeof error !=="undefined"){

                            console.log(error);
                        }

                    });

                //    .finally(() => this.loading = false)
            },
            resetForm() {
                this.name = "";
      
                this.result='';

                requestAnimationFrame(() => {
                    this.$refs.form.reset();
                });
            }
        }
    };

</script>

In corresponding Laravel controller method I have :

public function update_profile_now(Request $request) 
{

    $rules = array(

        'name' => 'required | min:4',
        'photo'=> 'image|mimes:jpeg,png,jpg|max:2048'
    );

    $validator = Validator::make(Input::all(), $rules);

    // Validate the input and return correct response
    if ($validator->fails())
    {
        return Response::json(array(
            'success' => false,
            'errors' => $validator->getMessageBag()->toArray()

        ), 200); 
    }

    //file uploading code goes here 

    return Response::json(array('success' => true), 200);

}

What I want is the form with a file input inside it will be submitted and then a JSON response will be sent from the method after file upload and other works.

So what should be the correct header or do I need to adopt any other means ?

5
  • you're trying to post the this.file as a json payload but with a multipart MIME type.. I guess it doesn't work this way.. Have a look at stackoverflow.com/a/43014086/6611700 and pass the name field also as a multipart field (and not json) Commented Dec 24, 2019 at 14:57
  • ' pass the name field also as a multipart field (and not json) ' - what do you mean ? How to do that ? Commented Dec 24, 2019 at 14:58
  • well, I'm assuming you need to use FormData#append for that.. Commented Dec 24, 2019 at 15:01
  • let me try with that Commented Dec 24, 2019 at 15:01
  • you right, it seems to be. Commented Dec 24, 2019 at 15:24

2 Answers 2

2

I guess using FormData API would work.

Below some examples:

How to post a file from a form with Axios axios post request to send form data

Sign up to request clarification or add additional context in comments.

Comments

-2

I Recommend using VeeValidation for validating your form after submitting it.

Its really simple and sweetest validation methods.

You can install it from here. VeeValidation Link

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.