POST, PUT & PATCH Requests with VueJS and Axios

Part 3 of 4 in Your Guide to Using an API with VueJS/NuxtJS and Axios
Dan Pastori avatar
Dan Pastori August 5th, 2020

These requests allow you to manipulate data on your API. If you want a refresher, visit Using Axios to Make API Requests With VueJS where we go over the basics of these requests. Using these requests properly and setting up your API to accept data through these request types ensure that developers know how to interact with your API the right way.

Let’s dive into these requests and how we can use them.

Types of Body Data

When working with these request types, you send data through the body to the server. The two formats we will use to send data to the server is through JSON and application/x-www-form-urlencoded.

By default Axios sends any data to the server as JSON. In most cases, this is fine. However, when you wish to upload a file, you will need to send the data as application/x-www-form-urlencoded. This is extremely important and cover it in-depth in Your Guide To Uploading Files with VueJS and Axios.

For now, let’s send a basic POST request to the server.

Sending POST Data to Create a Resource

When sending a POST request, you should assume that the server is going to create a new session (authorize a user) or create a new resource. Like we mentioned, this data will be sent as JSON by default or application/x-www-form-urlencoded. If you upload files to your server, you have to use a POST request.

Using VueJS

If you followed along in Configuring Axios Globally with VueJS, we set up Axios to be global. This means it should be present in any component. To send a POST request using Axios structure it like this:

axios.post('https://api.com/v1/resource', 
	{ 
		name: 'name', 
		date: 'date' 
	}, 
	{
		// Config
	}
);

Let’s break down this request example. The first parameter is the URL of the API endpoint we will be sending the data to. Like I mentioned, this should be the URL of an endpoint that creates a resource.

The second parameter is the data you will be sending to the server. Unlike a GET request, the POST request sends the data through the body of the request. In the example above we didn’t change anything, so by default this will be sent as JSON.

If you are uploading a file, as mentioned above, or if your server requires application/x-www-form-urlencoded data (which some do, especially legacy systems) we need to make a quick change to this request. To do that, we need to transform the data to be FormData .

To do this, we need to adjust the code to look like this:

let formData = new FormData();

formData.append('name', 'name');
formData.append('date', 'date');

axios.post('https://api.com/v1/resource', 
	formData, 
	{
		// Config
	}
);

What we do here, is we initialize a local variable named formData and create a new FormData object. We then append the data that we want to send using the method on the FormData object named append(). The first parameter of the append() method is the key . This is if you were to write an <input type="text" name="name"/> element. The second parameter is the value.

When submitting the form this way, it’s similar to sending the input from an HTML form to the server in the way that it’s encoded. You can append files to the FormData object which is how we upload files with axios.

Even though it’s similar, we will walk through how to do this with NuxtJS and cover some of the differences.

Using NuxtJS

So remember, NuxtJS has the Axios plugin and prefers the async/await syntax? Their preferred method looks just slightly different than the straight VueJS format.

Let’s take a look at the same POST request that we touched on first:

async nameOfFunction(){
    await this.$axios.$post('https://api.com/v1/resource', 
    {
        name: 'name',
        date: 'date'
    }, 
    {
        // Config
    })
}

Usually you’d wrap your Axios requests in NuxtJS in an async function. This Remember, you can put other functionality after the await . This would be methods to process or format your data or handle the successful POST request. You can also do this without async/await within nuxt by just calling:

this.$axios.$post('https://api.com/v1/resource', 
{
    name: 'name',
    date: 'date'
}, 
{
    // Config
})

You will have to handle the request with .then() at the end if you don’t use async/await.

When sending a request with FormData(), it’s exactly the same as VueJS where you have to create your FormData object and send it as the second parameter. Speaking of Form Data, it can get pretty cumbersome as you add fields to your form. So I created a mixin!

Transforming to Form Data Getting Cumbersome?

I wrote a VueJS mixin for that! As your form grows, you don’t want to keep writing code to send the data to the server when you add a form field. The VueJS mixin is below:

/**
 * Simple transformation to form data for uploading files
 * using VueJS and Axios.
 * 
 * Assuming that you pass your entire form as the `form`
 * paramter. For example:
 * 
 * data(){
 *      return {
 *          form : {
 *              name: 'Dan',
 *              job: 'Software Developer'
 *              website: 'https://serversideup.net'
 *              logo: FileList
 *          }
 *      }
 * }
 * 
 * this.transfromToFormData( this.form, ['logo'] );
 * 
 * For updating and sending a PUT request add:
 * 
 * this.transformToFormData( this.form, ['logo'], 'PUT' );
 * 
 * When sending a form as form data, you might need to send as
 * POST, but pass a _method parameter for 'PUT'.
 * 
 * 
 * 
 * @param {object} form The object representation of a form.
 * @param {array} fileKeys An array of keys that represent files
 * @param {string} method Optional: The method used to send the form such as 'PUT'
 */
transformToFormData( form, fileKeys, method = '' ){
    // Initializes the form dat object that we will be appending to
    let formData = new FormData();

    // Iterates over all elements in the form. Adds them to the
    // form data object. If the value is a file, we append the
    // file to the form data.
    for (let [key, value] of Object.entries(this.form)) {
        if( fileKeys.indexOf( key ) > -1 ){
            if( value !== '' ){
                formData.append( key, value[0] );
            }
        }else{
            // Booleans don't send as a true boolean through form data.
            // We send it as a 1 or 0 to make for easier processing on the
            // backend
            if( typeof value === "boolean" ){
                value = value ? 1 : 0;
            }
            formData.append( key, value );
        }
    }

    // If we have a method we need to send as, we append it here
    if( method != '' ){
        formData.append( '_method', method );
    }

    return formData;
},

So there’s a foreshadowing of one of the things we have to do when submitting data through PUT or PATCH (used mainly in a PHP/Laravel backend). Can you find it? We will touch on it soon!

Anyways, I have an example above in the comments on how to use this, but let’s walk through it.

The first parameter of this mixin is the form (see quick tip). This is all of the data you will be sending to the server. Typically this is in JSON object that we will iterate over and transform to form data.

Next up, we have fileKeys. This is an array that identifies any of the keys in your form array that are files. We want to handle those in a special manner. Since all v-model inputs that are of type="file" are a FileList, (for more information check out Mozilla’s documentation on this object), we want to grab the first value of the array, which is the individual file.

Finally we have the method parameter. This was the little “foreshadowing” for PUT and PATCH. By default this is an empty string. However, if you choose to pass PUT or PATCH you will get the _method form field attached to your request. With Laravel PHP specifically, this needs to be added when you send data as a FormData object. Even though you will be wanting to send a PUT or PATCH request, you must send the request as POST but with the _method set to PUT or PATCH Laravel will handle it correctly. We will go through an example in the next section.

The only other piece of the code I’d like to point out is the transformation to a Boolean value. If you have a checkbox that you want to send to the form and the value is true or false these will be sent as a String. We went to send these as a 1 or a 0 so we can perform any necessary operations on our backend.

Hopefully this helps! You can implement this mixin in both NuxtJS and VueJS and it will work for your form requests. It does, however, work best when combined with the next “quick tip”.

Quick Tip with Form Components

When working on forms in both NuxtJS and VueJS, a simple structure I’ve been incorporating into my components is setting up the form as an object in the data() of the component. Then each individual value would be a key on that object. This is especially helpful with large form components that compute data or have other inputs that you don’t want to necessarily send to the server. I saw this structure in the InertiaJS documentation and it made complete sense to me! Let’s take a look.

Say we have a component that has 3 inputs that we want to send to the server, first name, last name, and email address. I’d structure the component like this:

<template>
    <div>
        <label>First Name</label>
        <input type="text" v-model="form.first_name"/>

        <label>Last Name</label>
        <input type="text" v-model="form.last_name"/>

        <label>Email</label>
        <input type="text" v-model="form.email"/>

        <button v-on:click="submit()">Submit</button>
    </div>
</template>

<script>
export default {
    data(){
        return {
            form: {
                first_name: '',
                last_name: '',
                email: ''
            }
        }
    },

    methods: {
        submit(){
            axios.post('https://api.com/v1/user', this.form)
                .then(function( response ){
                    // Handle success
                }.bind(this));
        }
    }
}
</script>

So the big point I’m trying to get across is that anything sent to the server is in the form object. You can bind any input to the associated object like so: v-model="form.first_name". Now why do it this way? Even if you don’t have a big form, you can just pass the whole form directly to your API endpoint by passing this.form as the second parameter in your Axios request in the submit() method.

No passing 3 variables and updating it every time you add a new field. You can also easily transform to form data using the mixin above by passing this.form to the transformToFormData() mixin.

The other benefit is this allows you to keep some of the UI data outside of the scope of your form so it’s easier to manage. I really like this approach and I feel it leads to much cleaner development!

That’s the core of sending data to the server! Next up, let’s touch on PUT and POST.

Sending PUT/PATCH Data to Update a Resource

So there’s not really a lot of difference between PUT and PATCH compared to POST besides the Axios method you use. However, let’s touch on these.

Difference in URLs

In a properly structured RESTful API, you’d create a resource by sending a POST request to an endpoint with the name of the resource. For example, to create a User resource, you’d send a POST request to /api/v1/users or a URL that looks similar.

With a PUT/PATCH request, you want to update a specific user. This would mean passing a unique identifier to the server. Once again, in a properly structured RESTful API, this would append to the end of the url. Your API request to update a user would be /api/v1/users/{user} with {user} being the unique identifier of the user.

Determine the Method to Use

Remember when we discussed which method to use when updating a resource? If not, here’s a brief reminder, PUT is used to update an entire resource (send the whole updated resources to the server), and PATCH when you only have a piece of data to update.

The PUT method is called in Axios through VueJS like so:

axios.put('https://api.com/v1/resource/{id}', 
	{ 
		name: 'name', 
		date: 'date' 
	}, 
	{
		// Config
	}
);

and the PATCH method like this

axios.patch('https://api.com/v1/resource/{id}', 
	{ 
		name: 'name'
	}, 
	{
		// Config
	}
);

Sending FormData() is the exact same as through POST as well. The one MAJOR difference I wanted to point out when sending FormData() (which we touched a little bit on) is when sending it to a Laravel backend. You must send the _method set to PUT or PATCH and then make the request through POST. Even though we are making the request through POST since we have the _method set to PUT or PATCH Laravel will handle that correctly.

Using NuxtJS, you can use the same format as well. Just make sure you use the axios module like so:

this.$axios.$put('https://api.com/v1/resource', 
{
    name: 'name',
    date: 'date'
}, 
{
    // Config
})

Conclusion

Hopefully that helped clear up any confusion on sending data to an API! Next up, we will work on dealing with a lot of API requests and abstracting them into wrappers so you can re-use them easily.

Then we will go through some of the interceptors you can use to handle authentication errors and sending proper headers with requests for authentication.

Finally, we will deal with handling errors from the API request and properly displaying them.

Let me know if you have any questions and reach out in the comment section below or on Twitter (@danpastori).

Keep Reading
View the course View the Course Your Guide to Using an API with VueJS/NuxtJS and Axios
Up Next → Build an API Wrapper with VueJS & Axios

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.