DEV Community

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

Posted on

5

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

Image description

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! 🍀

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

Top comments (0)