Vue.js CRUD Example Tutorial From Scratch

Vue.js CRUD Example Tutorial From Scratch. As the topic suggests, we will perform crud operations using Vue.js and another backend framework to persist the data in the database. For this web application, I will use Node.js, MongoDB, Express.js and Axios library to perform the create, read, update, and delete(crud) operations in Vue.js We install Vue.js using Vue CLI.

Vue.js CRUD Example Tutorial

We start Vue.js CRUD Example Tutorial by installing Vue.js first.

#1: Install Vue.js

Okay, we install Vue.js using Vue CLI.

npm install -g @vue/cli
# or
yarn global add @vue/cli

Then create a new project using the following command.

vue create vuecrud

 

Vue.js CRUD Example Tutorial From Scratch

Now, go to the folder using the following command.

cd vuecrud

Now, open the project folder inside editor using the following command.

code .

#2: Install Vue Router, Axios, and vue-axios.

Okay, now go to the terminal and type the following command to install the vue-router, axios, and vue-axios dependencies.

npm install vue-router axios vue-axios --save

#3: Create three components.

Inside src >> components folder, create the following vue components.

  1. Create.vue
  2. Edit.vue
  3. Index.vue

Now, we will write the code inside all the three components one by one.

// Create.vue

<template>
    <div>
        Create Component
    </div>
</template>
<script>
export default {
    
}
</script>

Okay, now write the following code inside Edit.vue file.

// Edit.vue

<template>
    <div>
        Edit Component
    </div>
</template>
<script>
export default {
    
}
</script>

Also, write the following code inside Index.vue file.

// Index.vue

<template>
    <div>
        Index Component
    </div>
</template>
<script>
export default {
    
}
</script>

#4: Define Routing of the components.

Now, write the following code inside src >> main.js file.

// main.js

import Vue from 'vue'
import VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';

import App from './App.vue';

Vue.use(VueRouter);
Vue.use(VueAxios, axios);

Vue.config.productionTip = false

const router = new VueRouter({ mode: 'history' });

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

Now, we need to define routes array and add this component to this list.

Our final code of main.js file looks like below.

// main.js

import Vue from 'vue'
import VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';

import App from './App.vue';
import Create from './components/Create.vue';
import Edit from './components/Edit.vue';
import Index from './components/Index.vue';

Vue.use(VueRouter);
Vue.use(VueAxios, axios);

Vue.config.productionTip = false;

const routes = [
  {
    name: 'Create',
    path: '/create',
    component: Create
  },
  {
    name: 'Edit',
    path: '/edit',
    component: Edit
  },
  {
    name: 'Index',
    path: '/index',
    component: Index
  },
];

const router = new VueRouter({ mode: 'history', routes: routes });

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

I have imported all the components and then created an array that defines its name, path, and actual component. So we can access the different route of our application.

#5: Define the router view of the Vue application.

Next step is to write the following code inside src >> App.vue file.

// App.vue

<template>
  <transition name="fade">
      <router-view></router-view>
  </transition>
</template>

<script>

export default {
}
</script>

<style>
    .fade-enter-active, .fade-leave-active {
      transition: opacity .5s
    }
    .fade-enter, .fade-leave-active {
      opacity: 0
    }
</style>

So, we need to define the router-view element to show the different components output based on the URL.

If we try to access the URL like this: http://localhost:8080/create, then we can easily access the Create.vue component.

#6: Install Bootstrap 4.

Go to the terminal and install Bootstrap 4 using the following command.

npm install bootstrap --save

Now, inside main.js file, add the following code to include Bootstrap 4 css code.

// main.js

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';

Now, add the CSS classes inside App.vue file.

<template>
  <transition name="fade">
      <div class="container">
        <router-view></router-view>        
      </div>
  </transition>
</template>

#7: Add Bootstrap Navigation.

Now, write the following code inside App.vue file.

// App.vue

<template>
  <div id="app" class="container">
    <nav class="navbar navbar-expand-sm bg-light">
      <ul class="navbar-nav">
        <li class="nav-item">
          <router-link :to="{ name: 'Create' }" class="nav-link">Add Item</router-link>
        </li>
        <li class="nav-item">
          <router-link :to="{ name: 'Index' }" class="nav-link">All Items</router-link>
        </li>
      </ul>
    </nav>
    <transition name="fade">
      <div class="gap">
        <router-view></router-view>        
      </div>
    </transition>
  </div>
</template>

<script>

export default {
}
</script>

<style>
    .fade-enter-active, .fade-leave-active {
      transition: opacity .5s
    }
    .fade-enter, .fade-leave-active {
      opacity: 0
    }
    .gap {
      margin-top: 50px;
    }
</style>

#8: Add Routing Progress bar Indicator.

Type the following command to install nprogress. It is a library that provides us the UI component that displays the routing indicator.

npm install nprogress --save

Add its nprogress CSS inside a main.js file.

// main.js

import '../node_modules/nprogress/nprogress.css';

Now, we need to add a hook to the router object. So when we change the route, it starts the progress bar at the top and when the routing process finishes, we need to stop that progress bar from showing in the header.

// main.js

import Vue from 'vue'
import VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';
import NProgress from 'nprogress';

import App from './App.vue';
import Create from './components/Create.vue';
import Edit from './components/Edit.vue';
import Index from './components/Index.vue';

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import '../node_modules/nprogress/nprogress.css';

Vue.use(VueRouter);
Vue.use(VueAxios, axios);

Vue.config.productionTip = false;

const routes = [
  {
    name: 'Create',
    path: '/create',
    component: Create
  },
  {
    name: 'Edit',
    path: '/edit',
    component: Edit
  },
  {
    name: 'Index',
    path: '/index',
    component: Index
  },
];

const router = new VueRouter({ mode: 'history', routes: routes });

router.beforeResolve((to, from, next) => {
  if (to.name) {
      NProgress.start()
  }
  next()
});

router.afterEach(() => {
  NProgress.done()
});

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

#9: Create a form inside Create.vue component.

Now, write the following code inside Create.vue file.

// Create.vue

<template>
  <div class="container">
        <div class="card">
            <div class="card-header">
                <h3>Add Item</h3>
            </div>
            <div class="card-body">
                <form v-on:submit.prevent="addItem">
                    <div class="form-group">
                        <label>Item Name:</label>
                        <input type="text" class="form-control"/>
                    </div>
                    <div class="form-group">
                        <label>Item Price:</label>
                        <input type="text" class="form-control"/>
                    </div>
                    <div class="form-group">
                        <input type="submit" class="btn btn-primary" value="Add Item"/>
                    </div>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
export default {
  components: {
      name: 'AddItem'
  }
}
</script>

 

Vue CRUD Example

#10: Configure NodeJS Express MongoDB backend.

Now, we need to install the express.js framework and other dependencies via node package manager.

npm install --save express body-parser cors mongoose

Also, you need to install nodemon as a development dependency.

npm install nodemon --save-dev

Now,  create one file called server.js inside the root of the project and then write the following code inside the server.js file.

// server.js

const express = require('express'),
    path = require('path'),
    bodyParser = require('body-parser'),
    cors = require('cors'),
    mongoose = require('mongoose');

    const app = express();
    var port = process.env.PORT || 4000;

    var server = app.listen(function(){
        console.log('Listening on port ' + port);
    });

Okay, now create one folder inside root called config and inside that folder, create one file called DB.js.

// DB.js

module.exports = {
    DB: 'mongodb://localhost:27017/vuecrud'
};

Import this file into the server.js file and use mongoose to set up a database connection with MongoDB

I am writing whole server.js file so that nothing will left and lead us to error.

// server.js

const express = require('express'),
    path = require('path'),
    bodyParser = require('body-parser'),
    cors = require('cors'),
    mongoose = require('mongoose'),
    config = require('./config/DB');

    mongoose.Promise = global.Promise;
    mongoose.connect(config.DB).then(
        () => {console.log('Database is connected') },
        err => { console.log('Can not connect to the database'+ err)}
    );

    const app = express();
    app.use(express.static('public'));
    app.use(bodyParser.json());
    app.use(cors());
    const port = process.env.PORT || 4000;

    const server = app.listen(port, function(){
        console.log('Listening on port ' + port);
    });

Now, start the following servers.

  1. Start the MongoDB Database server using this command: mongod
  2. Start the Node.js server using this command: nodemon server

When you start the Node.js server, you can see in the console that, Our express application has been connected to the MongoDB database.

 

#11: Create Express routes for our application.

Now, we need to create two folders in a root called expressRoutes and models.

In models folder, create one model called Item.js.

// Item.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// Define collection and schema for Items
var Item = new Schema({
  name: {
    type: String
  },
  price: {
    type: Number
  }
},{
    collection: 'items'
});

module.exports = mongoose.model('Item', Item);

In the expressRoutes folder, create one file called itemRoutes.js.

Write the full backend Node.js CRUD code inside an itemRoutes.js file.

// itemRoutes.js

var express = require('express');
var app = express();
var itemRoutes = express.Router();

// Require Item model in our routes module
var Item = require('../models/Item');

// Defined store route
itemRoutes.route('/add').post(function (req, res) {
  var item = new Item(req.body);
      item.save()
    .then(item => {
    res.status(200).json({'item': 'Item added successfully'});
    })
    .catch(err => {
    res.status(400).send("unable to save to database");
    });
});

// Defined get data(index or listing) route
itemRoutes.route('/').get(function (req, res) {
  Item.find(function (err, items){
    if(err){
      console.log(err);
    }
    else {
      res.json(items);
    }
  });
});

// Defined edit route
itemRoutes.route('/edit/:id').get(function (req, res) {
  var id = req.params.id;
  Item.findById(id, function (err, item){
      res.json(item);
  });
});

//  Defined update route
itemRoutes.route('/update/:id').post(function (req, res) {
  Item.findById(req.params.id, function(err, item) {
    if (!item)
      return next(new Error('Could not load Document'));
    else {
      item.name = req.body.name;
      item.price = req.body.price;

      item.save().then(item => {
          res.json('Update complete');
      })
      .catch(err => {
            res.status(400).send("unable to update the database");
      });
    }
  });
});

// Defined delete | remove | destroy route
itemRoutes.route('/delete/:id').get(function (req, res) {
  Item.findByIdAndRemove({_id: req.params.id}, function(err, item){
        if(err) res.json(err);
        else res.json('Successfully removed');
    });
});

module.exports = itemRoutes;

Here, I have defined all the express routes to perform CRUD application at the database.

The itemRoutes.js file included inside the server.js file.

// server.js

const express = require('express'),
    path = require('path'),
    bodyParser = require('body-parser'),
    cors = require('cors'),
    mongoose = require('mongoose'),
    config = require('./config/DB');

    const itemRoutes = require('./expressRoutes/itemRoutes');

    mongoose.Promise = global.Promise;
    mongoose.connect(config.DB).then(
        () => {console.log('Database is connected') },
        err => { console.log('Can not connect to the database'+ err)}
    );

    const app = express();
    app.use(express.static('public'));
    app.use(bodyParser.json());
    app.use(cors());

    app.use('/items', itemRoutes);
    
    const port = process.env.PORT || 4000;

    const server = app.listen(port, function(){
        console.log('Listening on port ' + port);
    });

#12: Add the Item from Frontend.

At the frontend, we need to set up axios and fire up the HTTP Post call to the NodeJS server.

Also, we have setup the v-model to reflect all the textbox value in the item object. It is the simple two-way data binding.

// Create.vue

<template>
  <div class="container">
        <div class="card">
            <div class="card-header">
                <h3>Add Item</h3>
            </div>
            <div class="card-body">
                <form v-on:submit.prevent="addItem">
                    <div class="form-group">
                        <label>Item Name:</label>
                        <input type="text" class="form-control" v-model="item.name"/>
                    </div>
                    <div class="form-group">
                        <label>Item Price:</label>
                        <input type="text" class="form-control" v-model="item.price"/>
                    </div>
                    <div class="form-group">
                        <input type="submit" class="btn btn-primary" value="Add Item"/>
                    </div>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
export default {
  components: {
      name: 'AddItem'
  },
  data() {
      return {
          item: {}
      }
  },
  methods: {
      addItem() {
           let uri = 'http://localhost:4000/items/add';
            this.axios.post(uri, this.item).then((response) => {
                console.log(response.data)
            });
        }
    }
}
</script>

Insert the values and see if you get the success message in the console. Check in the MongoDB database.

 

MongoDB CRUD

#13: Display the Items.

Now, we need to route to the listing of the item, when we got the response. We can display all the items inside Index.vue file. So write the following code inside Index.vue file.

// Index.vue

<template>
    <div>
        <h1>Items</h1>

        <table class="table table-hover">
            <thead>
            <tr>
                <td>ID</td>
                <td>Item Name</td>
                <td>Item Price</td>
                <td>Actions</td>
            </tr>
            </thead>

            <tbody>
                <tr v-for="item in items" :key="item._id">
                    <td>{{ item._id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td><router-link :to="{name: 'Edit', params: { id: item._id }}" class="btn btn-primary">Edit</router-link></td>
                    <td><button class="btn btn-danger">Delete</button></td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

<script>

    export default {
        data(){
            return{
                items: []
            }
        },

        created: function()
        {
            this.fetchItems();
        },

        methods: {
            fetchItems()
            {
              let uri = 'http://localhost:4000/items';
              this.axios.get(uri).then((response) => {
                  this.items = response.data;
              });
            }
        }
    }
</script>

 

Vue Node CRUD example

#14: Perform Edit and Update operations.

Write the following code inside Edit.vue file.

// Edit.vue

<template>
  <div class="container">
        <div class="card">
            <div class="card-header">
                <h3>Edit Item</h3>
            </div>
            <div class="card-body">
                <form v-on:submit.prevent="updateItem">
                    <div class="form-group">
                        <label>Item Name:</label>
                        <input type="text" class="form-control" v-model="item.name"/>
                    </div>
                    <div class="form-group">
                        <label>Item Price:</label>
                        <input type="text" class="form-control" v-model="item.price" />
                    </div>
                    <div class="form-group">
                        <input type="submit" class="btn btn-primary" value="Update Item"/>
                    </div>
                </form>
            </div>
        </div>
    </div>
</template>
<script>
export default{
        data(){
            return{
                item:{}
            }
        },

        created: function(){
            this.getItem();
        },

        methods: {
            getItem()
            {
              let uri = 'http://localhost:4000/items/edit/' + this.$route.params.id;
                this.axios.get(uri).then((response) => {
                    this.item = response.data;
                });
            },

            updateItem()
            {
              let uri = 'http://localhost:4000/items/update/' + this.$route.params.id;
                this.axios.post(uri, this.item).then((response) => {
                  this.$router.push({name: 'Index'});
                });
            }
        }
    }
</script>

So, when the Edit.vue component is loaded, then we fetch the current data from the database and then display it inside a text box.

When the user changes the values of the textboxes, then it rewrites the old data and then sends that in the POST request and replace that data in the MongoDB database.

#15: Perform Delete operations.

Write the delete() function inside Index.vue file.

I am writing the whole Index.vue file.

// Index.vue

<template>
    <div>
        <h1>Items</h1>

        <table class="table table-hover">
            <thead>
            <tr>
                <td>ID</td>
                <td>Item Name</td>
                <td>Item Price</td>
                <td>Actions</td>
            </tr>
            </thead>

            <tbody>
                <tr v-for="item in items" :key="item._id">
                    <td>{{ item._id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td><router-link :to="{name: 'Edit', params: { id: item._id }}" class="btn btn-primary">Edit</router-link></td>
                    <td><button class="btn btn-danger"  v-on:click="deleteItem(item._id)">Delete</button></td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

<script>

    export default {
        data(){
            return{
                items: []
            }
        },

        created: function()
        {
            this.fetchItems();
        },

        methods: {
            fetchItems()
            {
              let uri = 'http://localhost:4000/items';
              this.axios.get(uri).then((response) => {
                  this.items = response.data;
              });
            },
            deleteItem(id)
            {
              let uri = 'http://localhost:4000/items/delete/'+id;
              this.items.splice(id, 1);
              this.axios.get(uri);
            }
        }
    }
</script>

Finally, we have completed Vue.js CRUD Example Tutorial. Thanks!!

I have put this code in the Github.

Github Code

Post Your Thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.

One Response