In this article, we learn how to perform crud operation in nuxt.js
Roadmap for creating CRUD in Nuxt.js
- Install nuxt.js
- Overview of Vuex
- Perform Crud in nuxt.js
1). Install Nuxt.js
- To get started creating our application we’ll be using create-nuxt-app. Create Nuxt App is a command line tool that helps you create and scaffold out your Nuxt applications. It helps you set up the default folder structure of your app, you can optionally install your preferred server-side framework like Express or Koa, and you can also install the Nuxt Axios module for easy Axios integration with your app.
- To get started, make sure you’re using a version of npm that’s 5.2.0 or higher. This will ensure you have npx installed, we’ll need this command.
- Then let’s run the following in your command in the terminal:
$ npx create-nuxt-app project-name
- To run the app that was just created in development mode, we’ll need to cd into the directory it created for us run the following command:
$ npm run dev
2). Overview of Vuex
- Vuex is a state management pattern + library. It is work as a centralized storage of our data for the whole application. The basic concept is derived from React’s Redux and Flux library. Vuex comes into the picture when our client side application becomes more and more complex. If our application is not more complex, then we should not use Vuex because after using it, if you will not handle it properly then It will become tedious and cumbersome
3). CRUD in Nuxt
- Install @nuxt/axios
npm install @nuxtjs/axios
- Registration.vue
<template> <div> <div class="container"> <b-form @submit="onSubmit" @reset="onReset" v-if="showForm"> <b-form-group id="input-group-1" label="Name:" label-for="input-1"> <b-form-input id="input-1" v-model="form.name" type="text" placeholder="Enter Name" required ></b-form-input> </b-form-group> <b-form-group id="input-group-2" label="Address:" label-for="input-2"> <b-form-input id="input-2" v-model="form.address" type="text" placeholder="Enter Address" required ></b-form-input> </b-form-group> <b-form-group id="input-group-3" label="Email address:" label-for="input-3" description="We'll never share your email with anyone else." > <b-form-input id="input-3" v-model="form.email" type="email" placeholder="Enter email" required ></b-form-input> </b-form-group> <b-form-group id="input-group-4" label="Contact:" label-for="input-4"> <b-form-input id="input-4" v-model="form.contact" type="number" placeholder="Enter Contact" required ></b-form-input> </b-form-group> <b-button type="submit" variant="primary">{{ isTableDataVisible ? "Submit" : "Update" }}</b-button> <b-button type="reset" variant="danger">Reset</b-button> </b-form> <div class="mt-10 container" v-if="isTableDataVisible"> <table class="table table-responsive"> <tbody> <tr> <th>Id</th> <th>Name</th> <th>Address</th> <th>Email</th> <th>Contact</th> <th>IsActive</th> <th></th> <th>Actions</th> </tr> <tr v-for="item in form.employeeData" :key="item.id"> <td>{{ item.id }}</td> <td>{{ item.name }}</td> <td>{{ item.address }}</td> <td>{{ item.email }}</td> <td>{{ item.contact }}</td> <td> <div class="switch"> <label> <input type="checkbox" :checked="item.isActive" /> <span class="lever"></span> </label> </div> </td> <td> <Editemployee :id="item.id" /> </td> <td> <div> <button class="btn btn-danger" @click="onDelete(item.id)"> Delete </button> </div> </td> </tr> </tbody> </table> </div> </div> </div> </template> <script> export default { props: { isTableDataVisible: { type: Boolean, default: true }, showForm: { type: Boolean, default: true } }, data() { return { form: { email: "", name: "", address: "", contact: "", employeeData: [] }, }; }, mounted() { this.getData(); this.$eventBus.on('get-data',this.getData); }, methods: { onSubmit(event) { event.preventDefault(); var params = { Name: this.form.name, Address: this.form.address, email: this.form.email, contact: this.form.contact, isActive: true }; this.$store .dispatch("createOrUpdateEmployee", params) .then(res => { if (res.data != null) { this.getData(); this.$notify({ text: "Record Inserted Successfully!" }); } }) .catch(error => { console.log(error); }); }, onDelete(id) { this.$store.dispatch("deleteEmployee", id).then(res => { if (res.data.isSuccess) { this.getData(); this.$notify({ text: "Record Deleted Successfully!" }); } }); }, getData() { this.$store.dispatch("getEmployees").then(res => { if (res.data.isSuccess) { this.form.employeeData = res.data.responseData; } }); }, onReset(event) { event.preventDefault(); // Reset our form values this.form.email = ""; this.form.name = ""; this.form.address = ""; this.form.contact = ""; // Trick to reset/clear native browser form validation state } } }; </script>
- Navbar.vue
<template> <div> <b-navbar toggleable="lg" type="dark" variant="info"> <b-navbar-brand href="#">Registration Form</b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav> <b-navbar-nav> <b-nav-item href="#">Edit</b-nav-item> </b-navbar-nav> <b-navbar-nav class="ml-auto"> <b-nav-form> <b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input> <b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button> </b-nav-form> <b-nav-item-dropdown text="Lang" right> <b-dropdown-item href="#">EN</b-dropdown-item> <b-dropdown-item href="#">ES</b-dropdown-item> <b-dropdown-item href="#">RU</b-dropdown-item> <b-dropdown-item href="#">FA</b-dropdown-item> </b-nav-item-dropdown> <b-nav-item-dropdown right> <template #button-content> <em>User</em> </template> <b-dropdown-item href="#">Profile</b-dropdown-item> <b-dropdown-item href="#">Sign Out</b-dropdown-item> </b-nav-item-dropdown> </b-navbar-nav> </b-collapse> </b-navbar> </div> </template>
- EditEmployee.vue
<template> <div> <b-button id="show-btn" @click="showModal(id)">Edit</b-button> <b-modal :id="id" hide-footer> <template #modal-title> Edit Employee Info </template> <div class="d-block"> <b-form @submit="onUpdate"> <b-form-group id="input-group-1" label="Name:" label-for="input-1"> <b-form-input id="input-1" v-model="form.name" type="text" placeholder="Enter Name" required ></b-form-input> </b-form-group> <b-form-group id="input-group-2" label="Address:" label-for="input-2"> <b-form-input id="input-2" v-model="form.address" type="text" placeholder="Enter Address" required ></b-form-input> </b-form-group> <b-form-group id="input-group-3" label="Email address:" label-for="input-3" description="We'll never share your email with anyone else." > <b-form-input id="input-3" v-model="form.email" type="email" placeholder="Enter email" required ></b-form-input> </b-form-group> <b-form-group id="input-group-4" label="Contact:" label-for="input-4"> <b-form-input id="input-4" v-model="form.contact" type="number" placeholder="Enter Contact" required ></b-form-input> </b-form-group> <input type="text" v-model="hiddenId" hidden /> <b-button type="submit" variant="primary"> Update </b-button> <b-button type="reset" variant="danger">Reset</b-button> </b-form> </div> <b-button class="mt-3" block @click="$bvModal.hide(id)">Close</b-button> </b-modal> </div> </template> <script> import Registration from "@/components/Registration"; export default { components: { Registration }, props: { id: String, }, data() { return { form: { email: "", name: "", address: "", contact: "", employeeData: [] }, hiddenId: "" }; }, mounted() { }, methods: { showModal(id) { this.$bvModal.show(id); this.getEmployeeDetailsById(id); }, onUpdate(event) { this.$bvModal.hide(this.id); event.preventDefault(); var params = { Id: this.hiddenId, Name: this.form.name, Address: this.form.address, email: this.form.email, contact: this.form.contact, isActive: true }; this.$store .dispatch("createOrUpdateEmployee", params) .then(res => { if (res.data != null) { this.$notify({ text: "Record Updated Successfully!" }); this.$eventBus.emit('get-data'); } }) .catch(error => { console.log(error); }); }, getEmployeeDetailsById(id) { this.$store.dispatch("getEmployeeByID", id).then(res => { if (res.data.isSuccess) { this.hiddenId = res.data.responseData.id; this.form.name = res.data.responseData.name; this.form.email = res.data.responseData.email; this.form.address = res.data.responseData.address; this.form.contact = res.data.responseData.contact; } }); } }, name: "Editemployee" }; </script> <style scoped></style>
- Layout/default.vue
<template> <main> <Navbar /> <notifications/> <Nuxt /> </main> </template>
- Pages/Index.vue
<template> <div> <Registration /> </div> </template> <script> export default {}; </script>
-
Plugins
1). vue-notification-client.js
2). vue-notification-server.js
3). vue-plugin-event-bus.js
1). vue-notification-client.js
import Vue from 'vue' import Notifications from 'vue-notification' Vue.use(Notifications)
2). vue-notification-server.js
import Vue from 'vue' import Notifications from 'vue-notification/dist/ssr.js' Vue.use(Notifications)
3). vue-plugin-event-bus.js
import Vue from "vue"; import VueEventBus from "vue-plugin-event-bus"; Vue.use(VueEventBus);
- store/action/index.js
export default { createOrUpdateEmployee({ commit, dispatch }, params) { const employeeData = params; commit("setData", {employeeData}); return this.$axios.post( `https://localhost:44377/api/Employee/CreateOrUpdateEmployees`, params ); }, getEmployees({ commit, dispatch }) { return this.$axios.get(`https://localhost:44377/api/Employee/GetEmployees`); }, getEmployeeByID({ commit, dispatch }, id) { return this.$axios.get( `https://localhost:44377/api/Employee/GetEmployeeById?id=` + id ); }, deleteEmployee({ commit, dispatch }, id) { return this.$axios.delete( `https://localhost:44377/api/Employee/DeleteEmployeeById?id=` + id ); } };
- store/mutations/index.js
export default { setData(state, payload) { Object.keys(payload).forEach(k => { state[k] = payload[k]; }) }, };
- store/index.js
import Vue from "vue"; import Vuex from "vuex"; import state from "./state"; import actions from "./actions"; import mutations from "./mutations"; Vue.use(Vuex); const createStore = () => { return new Vuex.Store({ state, actions, mutations, }); }; export default createStore;
- state.js
export default { employeeData:[] };
- nuxt.config.js
export default { // Global page headers: https://go.nuxtjs.dev/config-head head: { title: "nuxtcrud", htmlAttrs: { lang: "en" }, meta: [ { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { hid: "description", name: "description", content: "" }, { name: "format-detection", content: "telephone=no" } ], link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }] }, // Global CSS: https://go.nuxtjs.dev/config-css css: [ "bootstrap-css-only/css/bootstrap.min.css", "mdbvue/lib/css/mdb.min.css" ], // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins plugins: [ { src: "~/plugins/vue-notification-client", mode: "client" }, { src: "~/plugins/vue-notification-server", mode: "server" }, { src: "~/plugins/vue-plugin-event-bus.js", mode: "client" } ], // Auto import components: https://go.nuxtjs.dev/config-components components: true, // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules buildModules: [], // Modules: https://go.nuxtjs.dev/config-modules modules: [ // https://go.nuxtjs.dev/bootstrap "bootstrap-vue/nuxt", "@nuxtjs/axios" ], // Build Configuration: https://go.nuxtjs.dev/config-build build: { extend(config, ctx) {}, transpile: ["mdbvue/lib/components"] } };
- Output: