Vue JS is a framework that stands out for its simplicity and ease of learning. However, it is also a very powerful and robust framework. And when we talk about Web applications, a growing trend is the connection of our frameworks with an API. You may have asked yourself: “How to make this connection with Vue JS?” That’s what we will talk about in this article!
We will base our discussion on the project we developed in the article Vue JS - Introduction and Creating Your First Project.
In addition, we will use the API we developed in the article Creating PHP API with Laravel and PostgreSQL.
This will be interesting because we will see in practice how the connection of two different systems, with two different languages, occurs through the API.
To get started, let's start our API server in Laravel using the command php artisan serve. This command will return the following response:
Now let's access our HTML file that is using Vue and make the necessary adjustments.
Listing Users
The first adjustment we need to make is in the layout. Our API has the email field in its structure, but our HTML does not. We will add one more tag to also display the email of each registered user:
<input type="text" v-bind:value="user.email" v-on:change="setUser($event.target.value, user.id)">
Excellent! Now we can start implementing the API calls in our code. For this, we will use a JavaScript library called Axios. This library is becoming increasingly known due to the ease of its configuration and implementation. Furthermore, it makes requests based on promises, which helps us have truly asynchronous code.
The implementation of Axios in our project is quite simple, just like implementing Vue. Just add a tag with a CDN to your JS file:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Our goal is to list the registered users on our page as soon as it loads. Therefore, we need to make the request to our API before rendering our project. To do this, let’s put into practice a very interesting concept from Vue called “Lifecycle Hooks”, also known as “Vue Instance Lifecycle Triggers”.
It involves a series of methods that can be executed throughout the process of mounting the Vue instance, before and after its rendering. We teach each of the lifecycle hooks in our Complete Vue JS Course.
In this project, we will use the created() method.
We will add the following code to the Vue instance:
async created() {
let results = await axios.get('http://localhost:8000/api/users');
this.users = results.data;
}
Explanation: we made the request to our API URL through Axios. Then we selected the data returned by it (all users) and set them as the values of the users property of the Vue instance.
Since we used await to wait for the return of the Axios promise, it was necessary to create the created() method as async. This will be repeated in all methods that call any API route. We discuss the concept of async/await further in the article Asynchronous JavaScript: The Complete Guide - Part 5 - Understanding Async/Await.
Upon refreshing the page, we see the following result:
Excellent, the registered user in our Database was rendered correctly, through our API!
Creating a New User
The next step is to create a user. Our registration form has only one field, which is for the user's name. We need to make a small change, also adding the field for their email:
<div class="field">
<label for="email-input">Email</label>
<input type="email" name="email" id="email-input" placeholder="Enter the user's email" v-model="newUser">
</div>
Additionally, in the Vue instance we created a property that stores the name of the new user. However, we are now registering both the name and their email. We could create a new property called “newEmail” to store this information. However, that could become unsustainable over time.
To solve this issue, we will replace the newUser property with a formData call, which will initially have an empty object:
formData: {}
Now, the v-model directives in our form fields will contain the values of the “name” and “email” properties of the formData object:
<input type="text" name="username" id="username-input" placeholder="Enter the user's name" v-model="formData.name">
<input type="email" name="email" id="email-input" placeholder="Enter the user's email" v-model="formData.email">
Now we can have as many fields as we want.
Additionally, we will define that the formData object will be sent to Vue when the form is submitted:
<form v-on:submit.prevent="addUser(formData)">
Now let's make the call to our API. At this point, we may encounter another refactoring in the project. The URL “http://localhost:8000/api” will be repeated in all requests, as it is the base of our API. Therefore, it doesn't make sense to keep repeating this part in all our methods. We can store this information in a constant so that the code is a little cleaner:
const server = "http://localhost:8000/api";
Thus, the GET request we already created will look like this:
let results = await axios.get(`${server}/users`);
The method we will adapt for the API is the addUser() method. It will look as follows:
async addUser(data) {
if (!data.name) {
alert('Please provide the name');
} else if (!data.email) {
alert('Please provide the email');
} else {
let results = await axios.post(`${server}/users`, data);
this.users.push({
id: results.data.id,
name: results.data.name,
email: results.data.email
});
}
}
Explanation: we performed some checks in our code to ensure that the user didn't send any invalid information to the API. Then we defined the API request, now using the POST method and informing it of the values submitted by the form. Finally, we added the values returned by the API to our Vue instance, with the goal of updating the layout data at that moment.
Now, when we test sending a new user, we see the following in the user list:
Now our user was created through the API and has already been added to the page. The best part is that if we refresh the page, we will see that the user is still there!
Editing a User
To edit a user, we are using the setUser() method. Previously, we were only informing the value of a new name. However, now we need to inform more than just one piece of data. Let's adapt the HTML so that we provide the entire user object to the method:
<input type="text" v-model="user.name" v-on:change="setUser(user)">
<input type="text" v-model="user.email" v-on:change="setUser(user)">
Note that we also changed the v-bind directive to v-model, so we can change the value of the user property when typing the new value.
Now let's adapt the setUser() method so that it makes the Laravel API call, informing the PATCH method to it. Our method will look like this:
async setUser(data) {
if (!data.name) {
alert('Please provide the name');
} else if (!data.email) {
alert('Please provide the email');
} else {
await axios.patch(`${server}/users/${data.id}`, data);
}
}
Notice that we added some checks to ensure that the name and email were provided to the method and made the API call, quite similar to the addUser() method. This is already sufficient. By changing the value of any field, it will also be saved via the API.
Deleting a User
Finally, we arrive at the deletion method. The click event on the delete button will remain the same, only the removeUser() method will change. It will look like this:
async removeUser(id) {
await axios.delete(`${server}/users/${id}`);
this.users = this.users.filter(user => {
return (user.id != id);
})
}
Explanation: we added the call to our API using the DELETE method. In addition, we kept the filter() method on the users property so that the deleted user is removed from our page. Now, if we click the “Delete” button in any row, the user will be removed, not only from the page but also from the Database!
You can find the codes developed in this article on our GitHub.
In this article, we learned how to connect a Vue JS application to an API and manipulate the call to its routes. This knowledge can be a differential when we work with web applications development.
If you wish, you can send topic suggestions by clicking here. Until the next article :)