DEV Community

Cover image for Vue3 crud app with json-server and axios
Negin Saljooghi
Negin Saljooghi

Posted on

Vue3 crud app with json-server and axios

Hi, here we want to make a simple crud app with Vue.js by using json-server, axios and Tailwind CSS for styling.
In this app we have two fields: name, username with three default values that we can edit, delete them or add a new one.
You can find source code here: source code

let's start this project together step by step:


1. Setup project

Run vue create vue-crud-app to create a new app. Open the project and run npm run serve to see the project in your browser and then open a new terminal and run this command to start json-server :npx json-server --watch data/data.json --port 8000.


2. Files & Folder

we just need App.vue file and delete other files. Then create two folders: components & data.

Components :

In the src folder, create a components folder to put all of our files inside it. We have five components inside this folder :

AddUser.vue: to add a user.

EditUser.vue: to edit a user.

UserList.vue: to show all users.

Home.vue: it is our homepage,where we show UserList.vue & AddUser.vue components.

UserDetail.vue: to show user detail.

data:

It is in the root folder. Inside this folder create a file and called it data.json and put all of our data inside it.

{ "users":[ { "name":"Negin", "username":"negin007", "id":1 }, { "name":"Craig", "username":"benisphere", "id":2 }, { "name":"Ben", "username":"siliconeidolon", "id":3 } ] } 
Enter fullscreen mode Exit fullscreen mode

3.Code

router.js

  • src/router.js .
  • It is used to define and configure the router for our application & allowing you to navigate between different pages or components based on the URL.
const routes = [ { path: "/", name: "users", component: () => import("./components/Home") }, { path: "/user/:id", name: "editUser", component: () => import("./components/EditUser") // props: true }, { path: "/addUser", name: "addUser", component: () => import("./components/AddUser") }, { path: "/users/:id", name: "userDetail", component: () => import("./components/UserDetail") } ]; 
Enter fullscreen mode Exit fullscreen mode

App.vue

  • src/App.vue.
  • It has blockquote tag and <router-view/> to display the content of your different pages.
<template> <blockquote class="text-2xl font-semibold italic text-center text-blue-500 my-10"> <span class="mx-2 before:block before:absolute before:-inset-1 before:-skew-y-3 before:bg-pink-400 relative inline-block"> <span class="relative text-white "> CRUD App </span> </span> with Vue.js </blockquote> <router-view /> </template> <script> export default {}; </script> 
Enter fullscreen mode Exit fullscreen mode

Home.vue

  • src/components/Home.vue.

  • It contains UserList and AddUser components.we fetch users here and then pass it as props to these components.

<template> <div class="max-w-xl pb-8 mx-auto px-5 bg-slate-100"> <UserList :users="users" @userDeleted="handleUserDeleted" /> <AddUser :users="users" /> </div> </template> <script> import UserList from "./UserList.vue"; import AddUser from "./AddUser.vue"; import axios from 'axios'; export default { components: { UserList, AddUser, }, data() { return { users: [] } }, mounted() { this.fetchUsers(); }, methods: { fetchUsers() { axios .get('http://localhost:8000/users') .then((res) => { this.users = res.data }) .catch(err => console.log(err)) }, handleUserDeleted(userId) { this.users = this.users.filter((user) => user.id !== userId); } } }; </script> 
Enter fullscreen mode Exit fullscreen mode

UserList

  • src/components/UserList.vue.
  • It shows list of users with two buttons for edit and delete each user.By click on name you can see user detail.
  • we have two methods:

deleteUser : for delete each user.
updateUser : for navigate to edit page and then edit name & username.

<template> <div v-if="users.length" class='py-5'> <div v-for="user in users " :key="user.id" class='flex justify-between border-b-4'> <div class="flex "> <router-link :to="'/users/' + user.id"> <p class='my-3 px-3'>{{ user.name }}</p> </router-link> <p class='my-3 px-3'>{{ user.username }}</p> </div> <div class="flex "> <p @click="updateUser(user.id)" class='mx-2 my-3 px-2 py-1 text-green-800 hover:bg-green-400 hover:rounded-md hover:border hover:border-green-800'>EDIT</p> <p @click="deleteUser(user.id)" class='my-3 px-2 py-1 text-red-800 hover:bg-red-400 hover:rounded-md hover:border hover:border-red-800'>DELETE</p> </div> </div> </div> </template> <script> import axios from 'axios'; import UserDetail from './UserDetail.vue'; export default { components: { UserDetail, }, props: ['users'], methods: { deleteUser(id) { axios .delete(`http://localhost:8000/users/${id}`) .then(() => { this.$emit('userDeleted', id) }) .catch((error) => { console.log(error) }) }, updateUser(id) { this.$router.push(`/user/${id}`) } } } </script> 
Enter fullscreen mode Exit fullscreen mode

EditUser

  • src/components/EditUser.vue.
  • We have two input fields for showing name & username.
  • Two methods for updating user and cancel editing and back to home page.
<template> <div class="flex items-center justify-center"> <form @submit.prevent="handleSubmit"> <div class='flex flex-col justify-center items-center bg-slate-100 p-10 mt-10 rounded-md'> <input v-model="name" class='my-2 px-5 py-1 rounded-full border border-gray-600' /> <input v-model="username" class='my-2 px-5 py-1 rounded-full border border-gray-600' /> </div> <div class="flex my-2 mx-20"> <button class='text-white mx-1 px-5 py-1 rounded-full bg-blue-500 hover:bg-blue-700'>Update User</button> <button class='text-white mx-1 px-5 py-1 rounded-full bg-blue-500 hover:bg-blue-700' @click="backToHome">Cancel</button> </div> </form> </div> </template> <script> import axios from 'axios'; export default { data() { return { id: this.$route.params.id, name: "", username: "" } }, mounted() { axios .get('http://localhost:8000/users/' + this.id) .then((user) => { this.name = user.data.name; this.username = user.data.username; }) }, methods: { handleSubmit() { axios .put('http://localhost:8000/users/' + this.id, { name: this.name, username: this.username, }) .then(() => { this.$router.push("/"); }) }, backToHome() { this.$router.push('/') } }, } 
Enter fullscreen mode Exit fullscreen mode

UserDetail

  • src/components/UserDetail.vue.
  • To see user detail,here: name & username.
<template> <div class="max-w-xl pb-8 mx-auto px-5 bg-slate-100"> <div class="flex flex-col text-center py-5 "> <p class='px-3 py-3 border-b-4'>Name : {{ user ? user.name : '' }}</p> <p class='px-3 py-3'>UserName : {{ user ? user.username : '' }}</p> </div> </div> </template> <script> import axios from 'axios'; export default { data() { return { user: null, id: this.$route.params.id } }, mounted() { this.fetchUser(); }, methods: { fetchUser() { axios .get('http://localhost:8000/users/' + this.id) .then((res) => { this.user = res.data }) .catch(err => console.log(err)) } } } </script> 
Enter fullscreen mode Exit fullscreen mode

AddUser

  • src/components/AddUser.vue.
  • It has two fields for add name and username & a handleSubmit method to add user to list of users.
<template> <form @submit.prevent="handleSubmit"> <div class='flex flex-col justify-center items-center '> <div class='mb-2'> <input class='px-3 py-1 rounded-full border border-gray-600' v-model="name" placeholder="Name" /> </div> <div class='mb-2'> <input class='px-3 py-1 rounded-full border border-gray-600' v-model="username" placeholder="UserName" /> </div> <div class='mb-2'> <button class="bg-blue-500 hover:bg-blue-700 text-white py-1 px-3 rounded-full"> Add </button> </div> </div> </form> </template> <script> import axios from 'axios'; export default { props: ['users'], data() { return { name: '', username: '' } }, methods: { handleSubmit() { axios .post("http://localhost:8000/users", { name: this.name, username: this.username, }) .then((response) => { const data = response.data; this.users.push(data); this.name = ""; this.username = ""; }); }, } } </script> 
Enter fullscreen mode Exit fullscreen mode

Now here we go! We created a simple crud app with Vue.js, json-server, axios and Tailwind CSS.

Thank you for reading! 🍀

Top comments (0)