Vue 2 MEVN Tutorial-Build Full Stack Vue CRUD App

In this MEVN stack tutorial, we will learn how to create a MEVN stack app.

Build MEVN Stack CRUD Application

We will see how to create a Full-stack single-page application with Vue.

We will be creating a simple yet best Student Record Management System. This system efficiently allows the user to perform CRUD (CREATE, READ, UPDATE & DELETE) operations.

 

We will create our server using Node and Express.js and store student records. We will use MongoDB. We will manage the front end of the application with Vue.js.

 

Now, let’s start coding the MEVN Stack app with an example:

 

Vue Js 2 Full Stack CRUD Example

Step 1- Create a New Vue Project

Step 2- Adding Bootstrap In Vue

Step 3- Build Vue Component

Step 4- Enable Vue Router

Step 5- Setting Up Navigation And Router View

Step 6- Add Axios In Vue

Step 7- Build Form In Vue With Bootstrap

Step 8- Setting Up Node Server Environment

Step 9- Create Mongoose Model

Step 10- Create Route In Node/Express App

Step 11- Start Node/Express App

Step 12- Create Student Data With Axios POST

Step 13- Show Data List & Delete Data In Vue

Step 14- Update Data With POST Request

Step 15- Conclusion

 

Step 1- Create A New Vue Project

In the very first step, we will install the Vue project for which we must have Vue CLI installed on our development system. For that, we run the following command to install Vue CLI:

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

 

Now, we will use the following command to install the Vue project:

vue create vue-mevn-stack-app

 

Here, we will head over to the Vue project:

cd vue-mevn-stack-app

 

To remove the multi-word error warning, we have to add the given code in the vue.config.js file:

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
})

 

Error: digital envelope routines::unsupported
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'

 

To remove the above error for invoking the app, do remember to update the “scripts”: [] array in the package.json file.

"scripts": {
    "serve": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
    "build": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
    "lint": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service lint"
},

 

Then, we run the command to see the Vue app on the browser

npm run serve

 

Step 2- Adding Bootstrap In Vue

Here, we will install the Bootstrap 4 UI framework:

npm install bootstrap

 

Then, we will open the main.js file and import the Bootstrap framework path inside of it:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import 'bootstrap/dist/css/bootstrap.min.css'
Vue.config.productionTip = false
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

 

Step 3- Build Vue Components

In this step, we will head over to the src/components directory for which we have to create the following components. These components will handle the data in our full-stack Vue.js application.

  • CreateComponent.vue
  • EditComponent.vue
  • ListComponent.vue

Afterward, we need to open the src/CreateComponent.vue file and add the following code inside it:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <!-- Content goes here -->
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
            }
        }
    }
</script>
</div>

 

Then, we will open the src/EditComponent.vue file and add the following code inside it:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <!-- Update Student content -->
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
            }
        }
    }
</script>

 

Here, we have to open the src/ListComponent.vue file and add the following code to it:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <!-- Display Student List -->
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
            }
        }
    }
</script>

 

Step 4- Enable Vue Router

In this step, we have to install the Vue router package in the Vue app:

npm add vue-router@^3.1.6

 

Now, we will open the src/router/index.js and replace the existing code with the given code:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
  {
    path: '/',
    name: 'home',
    component: () => import('../components/CreateComponent')
  },
  {
    path: '/view',
    name: 'view',
    component: () => import('../components/ListComponent')
  },
  {
    path: '/edit/:id',
    name: 'edit',
    component: () => import('../components/EditComponent')
  }
]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  
++++routes
})
export default router

 

Step 5- Setting Up Navigation With Bootstrap And Router View In Vue

In this step, we need to go to the src/App.vue file where we will define the Bootstrap Navigation Component, router-view directive and the router-link directive.

The <router-link> is the component for facilitating user navigation in a router-enabled Vue app.

The <router-view> component is the main component that is responsible for rendering the matched component for the provided path.

<template>
  <div>
    <!-- Nav bar -->
    <nav class="navbar navbar-dark bg-primary justify-content-between flex-nowrap flex-row">
      <div class="container">
        <a class="navbar-brand float-left">MEVN Stack Example</a>
        <ul class="nav navbar-nav flex-row float-right">
          <li class="nav-item">
            <router-link class="nav-link pr-3" to="/">Create Student</router-link>
          </li>
          <li class="nav-item">
            <router-link class="nav-link" to="/view">View Students</router-link>
          </li>
        </ul>
      </div>
    </nav>
    <!-- Router view -->
    <div class="container mt-5">
      <router-view></router-view>
    </div>
  </div>
</template>

 

Step 6- Add Axios In Vue To handle HTTP Requests

Further, we will run the below command to install Axios which is a promise-based HTTP client for the browser and node.js:

npm install axios

 

Step 7- Build Form In Vue With Bootstrap 4

We require to store the data in the MEVN stack app. hence, we will build a Vue form using Bootstrap Form Component.

We need to open the components/CreateComponent.vue file and then place the following code in it:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <h3 class="text-center">Create Student</h3>
            <form @submit.prevent="handleSubmitForm">
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" class="form-control" v-model="student.name" required>
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="email" class="form-control" v-model="student.email" required>
                </div>
                <div class="form-group">
                    <label>Phone</label>
                    <input type="text" class="form-control" v-model="student.phone" required>
                </div>
                <div class="form-group">
                    <button class="btn btn-danger btn-block">Create</button>
                </div>
            </form>
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                student: {
                   name: '',
                   email: '',
                   phone: ''
                }
            }
        },
        methods: {
            handleSubmitForm() { }
        }
    }
</script>

 

We have created a basic form with the name, email and phone number fields using the Bootstrap Form Component.

The student object works with two-way data binding approach. It merely means that any data-related changes affecting the model are immediately propagated to the matching view.

Below given is the form:

Build Form in Vue with Bootstrap 4

 

Step 8- Setting Up Node Server Environment

Now, we need to create REST APIs using Node + Express & MongoDB in Vue application. Then, we will create a backend folder at the root of the Vue project:

mkdir backend && cd backend

Now, we generate a separate package.json for the node server:

npm init

Afterward, we run the below command to install the following dependencies for Node/Express js:

npm i body-parser cors express mongoose

In addition, we have to install a nodeman server as a development dependency so that we need not restart every time, we change our server code.

Nodeman automates the server starting process:

npm install nodemon

 

Step 9- Create Mongoose Model

Here, we will create models/Student.js and paste the given code inside the file. We will define the name, email and phone values inside the Student model:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let studentSchema = new Schema({
  name: {
    type: String
  },
  email: {
    type: String
  },
  phone: {
    type: Number
  },
}, {
  collection: 'students'
})
module.exports = mongoose.model('Student', studentSchema)

 

Step 10- Create Route In Node/Express App

Now, we need to create a backend/routes directory. Then, we have to create the student.route.js file and place the following code inside it:

const express = require('express');
const studentRoute = express.Router();
// model
let StudentModel = require('../models/Student');
studentRoute.route('/create-student').post((req, res, next) => {
  StudentModel.create(req.body, (error, data) => {
  if (error) {
    return next(error)
  } else {
    res.json(data)
  }
})
});
studentRoute.route('/').get((req, res, next) => {
    StudentModel.find((error, data) => {
     if (error) {
       return next(error)
     } else {
       res.json(data)
     }
   })
 })
studentRoute.route('/edit-student/:id').get((req, res, next) => {
   StudentModel.findById(req.params.id, (error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
})
// Update
studentRoute.route('/update-student/:id').put((req, res, next) => {
  StudentModel.findByIdAndUpdate(req.params.id, {
    $set: req.body
  }, (error, data) => {
    if (error) {
      return next(error);
    } else {
      res.json(data)
      console.log('Student successfully updated!')
    }
  })
})
// Delete
studentRoute.route('/delete-student/:id').delete((req, res, next) => {
  StudentModel.findByIdAndRemove(req.params.id, (error, data) => {
    if (error) {
      return next(error);
    } else {
      res.status(200).json({
        msg: data
      })
    }
  })
})
module.exports = studentRoute;

We defined the routes that will communicate with the server using the Axios library. We can perform CRUD operations using the GET, POST, UPDATE & DELETE methods. Then, we have to create the backend/index.js file and place the given code that contains the Node server settings:

const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
// Connect mongoDB
mongoose
  .connect('mongodb://127.0.0.1:27017/mydatabase')
  .then((x) => {
    console.log(`Connected to Mongo! Database name: "${x.connections[0].name}"`)
  })
  .catch((err) => {
    console.error('Error connecting to mongo', err.reason)
  })
const studentAPI = require('../backend/routes/student.route')
const app = express()
app.use(bodyParser.json())
app.use(
  bodyParser.urlencoded({
    extended: false,
  }),
)
app.use(cors())
// API
app.use('/api', studentAPI)
// Create port
const port = process.env.PORT || 4000
const server = app.listen(port, () => {
  console.log('Connected to port ' + port)
})
// Find 404
app.use((req, res, next) => {
  next(createError(404))
})
// error handler
app.use(function (err, req, res, next) {
  console.error(err.message)
  if (!err.statusCode) err.statusCode = 500
  res.status(err.statusCode).send(err.message)
})

 

Step 11- Start Node/Express App

We have built the following API using Node and Express in Vue.js:

Method API
GET http://localhost:4000/api
POST /api/create-student
GET /api/edit-student/:id
POST /api/update-student/:id
DELETE /api/delete-student/:id

Now, we open a new terminal window and start the MongoDB:

mongo

Afterward, we will open a new terminal window and start the nodeman server:

nodemon

Again, we have to open another terminal window and start the Vue app:

npm run serve

 

Step 12- Create Student Data With Axios POST

The Axios POST method takes the REST API and makes the POST request to the server. It creates the student data that we are adding to the MongoDB database.

Further, we add the given code inside the components/CreateComponent.vue file:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <h3 class="text-center">Create Student</h3>
            <form @submit.prevent="handleSubmitForm">
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" class="form-control" v-model="student.name" required>
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="email" class="form-control" v-model="student.email" required>
                </div>
                <div class="form-group">
                    <label>Phone</label>
                    <input type="text" class="form-control" v-model="student.phone" required>
                </div>
                <div class="form-group">
                    <button class="btn btn-danger btn-block">Create</button>
                </div>
            </form>
        </div>
    </div>
</template>
<script>
    import axios from "axios";
    export default {
        data() {
            return {
                student: {
                   name: '',
                   email: '',
                   phone: ''
                }
            }
        },
        methods: {
            handleSubmitForm() {
                let apiURL = 'http://localhost:4000/api/create-student';
                
                axios.post(apiURL, this.student).then(() => {
                  this.$router.push('/view')
                  this.student = {
                    name: '',
                    email: '',
                    phone: ''
                  }
                }).catch(error => {
                    console.log(error)
                });
            }
        }
    }
</script>

 

Step 13- Show The Data List & Delete Data In Vue

Now, we will show the data in the tabular form using the Bootstrap Table Components and we will make the axios.get() request to render the data from the server.

Then, we have to add the below code inside the components/ListComponent.vue file:

<template>
    <div class="row">
        <div class="col-md-12">
            <table class="table table-striped">
                <thead class="thead-dark">
                    <tr>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Phone</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="student in Students" :key="student._id">
                        <td>{{ student.name }}</td>
                        <td>{{ student.email }}</td>
                        <td>{{ student.phone }}</td>
                        <td>
                            <router-link :to="{name: 'edit', params: { id: student._id }}" class="btn btn-success">Edit
                            </router-link>
                            <button @click.prevent="deleteStudent(student._id)" class="btn btn-danger">Delete</button>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</template>
<script>
    import axios from "axios";
    export default {
        data() {
            return {
                Students: []
            }
        },
        created() {
            let apiURL = 'http://localhost:4000/api';
            axios.get(apiURL).then(res => {
                this.Students = res.data;
            }).catch(error => {
                console.log(error)
            });
        },
        methods: {
            deleteStudent(id){
                let apiURL = `http://localhost:4000/api/delete-student/${id}`;
                let indexOfArrayItem = this.Students.findIndex(i => i._id === id);
                if (window.confirm("Do you really want to delete?")) {
                    axios.delete(apiURL).then(() => {
                        this.Students.splice(indexOfArrayItem, 1);
                    }).catch(error => {
                        console.log(error)
                    });
                }
            }
        }
    }
</script>
<style>
    .btn-success {
        margin-right: 10px;
    }
</style>

 

To delete the student object from the database, we defined the deleteStudent() function and bound it to click event with an id parameter.

The apiURL contains the api/delete-student/:id API, to find out the index of the clicked student data index from the Students array, we took the help of findIndex() method:

Show Data List & Delete Data in Vue

Step 14- Update Data With POST Request

Here, we will add the following code inside the components/EditComponent.vue file:

<template>
    <div class="row justify-content-center">
        <div class="col-md-6">
            <h3 class="text-center">Update Student</h3>
            <form @submit.prevent="handleUpdateForm">
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" class="form-control" v-model="student.name" required>
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="email" class="form-control" v-model="student.email" required>
                </div>
                <div class="form-group">
                    <label>Phone</label>
                    <input type="text" class="form-control" v-model="student.phone" required>
                </div>
                <div class="form-group">
                    <button class="btn btn-danger btn-block">Update</button>
                </div>
            </form>
        </div>
    </div>
</template>
<script>
import axios from "axios";
export default {
    data() {
        return {
            student: { }
        }
    },
    created() {
        let apiURL = `http://localhost:4000/api/edit-student/${this.$route.params.id}`;
        axios.get(apiURL).then((res) => {
            this.student = res.data;
        })
    },
    methods: {
        handleUpdateForm() {
            let apiURL = `http://localhost:4000/api/update-student/${this.$route.params.id}`;
            axios.put(apiURL, this.student).then((res) => {
                console.log(res)
                this.$router.push('/view')
            }).catch(error => {
                console.log(error)
            });
        }
    }
}
</script>

Here, we have to deal with two things and we have to render the data when the user lands on student details component and make the post request to update the information on the server.

to get the current id from the existing URL, use this.$route.params.id Vue API. Using the same API, we can get the id from the URL and can update the database values by consuming the api/update-student/:id API.

 

Step 15- Conclusion

This is the final step of this MEVN Stack tutorial, we follow the mentioned instructions to start and test the app:

# Start MEVN Stack app.
```
Git clone https://github.com/SinghDigamber/vue-mevn-stack-app.git
# get inside the project
cd vue-mevn-stack-app
# install the required packages
npm install
# start the vue app on http://localhost:8080
npm run serve
# get into node server
cd backend
# add required packages
npm install
# start database
mongo
# Start node server
nodemon

```

 

Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *