Node Express.js, Vue.js & Mongoose|MongoDB Tutorial — CRUD By Example

Throughout this tutorial, you'll be using Node.js, Express.js and Vue.js to learn by example how to create a full-stack CRUD (Create, Read, Update and Delete) application. For database we'll be using MongoDB and Mongoose.

Express is a Node web framework that provides developers with essential elements to build web applications such as routing and templates etc.

Introduction

In this tutorial, we'll use Vue for the front-end and Node for the back-end of a full-stack web application.

The example application we'll be building will allow you to create, read, update and delete records from a MongoDB database with a Vue front-end interface. Express will be used for routing and REST API endpoints.

Start by creating a folder for your project by running the following command:

mkdir VueJSNodeProject

Navigate inside your newly created project and create a package.json file:

cd VueJSNodeProject
touch package.json

Open the package.json file and add the following content:

{
  "name": "vuenodeproject",
  "version": "1.0.0",
  "description": "A Vue with Node and Express back end Project",
  "scripts": {
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
  }
}

Installing Back-End Dependencies

Now let's install the required dependencies:

npm install --save express body-parser cors mongoose nodemon

Creating The Express Server

Inside your project's root folder create a server.js file and add the following content:

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

mongoose.connect("mongodb://localhost:27017/vuenodedb").then(
          () => {console.log('Database connection is successful') },
          err => { console.log('Error when connecting to the database'+ err)}
);
const app = express();
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(cors());

var port = process.env.PORT || 4000;

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

You need to install MongoDB database system on your development machine.

Creating the Mongoose Model(s): Todo

Create a models folder inside your project and add a Todo.js file with the following content:

const mongoose = require('mongoose');

const TodoSchema = mongoose.Schema({
    name: String
}, {
    timestamps: true
});

module.exports = mongoose.model('Todo', TodoSchema);

Our Todo model is very simple as it only contains a name field of type String. We have also set timestamps to true which automatically adds two new fields: createdAt and updatedAt to the schema.

Creating Express Routes

First, let's require the Todo model:

var Todo = require('./models/Todo');

Next, let's instantiate an Express router:

var router = express.Router();

Creating a Todo: Express.js POST Route Example

Now let's add a POST route that handles HTTP POST requests. In the same file add the following code:

...
router.route('/create').post((req, res) => {
  var todo = new Todo(req.body);
   todo.save().then( todo => {
   res.status(200).json({'message': 'Todo successfully added '});
   })
   .catch(err => {
    res.status(400).send("Error when saving to database");
   });
});

Getting Todos: Express.js GET Route Example

Next, let's add a GET route that handles HTTP GET requests. Add the following code:

router.route('/todos').get((req, res) => {
  Todo.find((err, todos) =>{
    if(err){
      console.log(err);
    }
    else {
      res.json(todos);
    }
  });
});

Getting a Todo by Id: Express.js GET by Id Route Example

router.route('/todos/:id').get((req, res) => {
  var id = req.params.id;
  Todo.findById(id, (err, todo) =>{
      res.json(todo);
  });
});

Updating a Todo by Id: Express.js PUT Route Example

router.route('/todos/:id').put((req, res) => {
  Todo.findById(req.params.id, (err, todo) => {
    if (!todo)
      return next(new Error('Error getting the todo!'));
    else {
      todo.name = req.body.name;
      todo.save().then( todo => {
          res.json('Todo updated successfully');
      })
      .catch(err => {
            res.status(400).send("Error when updating the todo");
      });
    }
  });
});

Deleting a Todo by Id: Express.js DELETE Route Example

router.route('/todos/:id').get((req, res) => {
  Todo.findByIdAndRemove({_id: req.params.id}, (err,todo) =>{
        if(err) res.json(err);
        else res.json('Todo successfully removed');
    });
});

Starting your Express.js API Back-End

node server.js

You should have the following output in the terminal:

Listening on port 4000

Installing Vue CLI v3

We'll use the Vue CLI to generate the Vue front-end application. Let's start by installing the Vue CLI if you have not done so yet using the following command:

npm install --global @vue/cli 

Generating a Vue Application Using Vue CLI v3

Let's now generate a new Vue application inside our project's root folder

$ vue create frontend

Next navigate inside your frontend folder and install Axios by running the following command:

$ npm install --save axios

Axios is a Promise based HTTP client that we'll be using to make HTTP calls from our Vue front-end application to our Express.js REST API backend running at http://localhost:4000 with CORS enabled.

Creating Vue Components

Inside frontend/src/components add two Vue components:

  • CreateTodo.vue: for creating todos.
  • ListTodo.vue: for displaying fetched todos.

Creating a Todo

Open components/CreateTodo.vue and add the following content:

<template>
<div id="container" class="container">

<div class="row">

<div class="col-sm-8 offset-sm-2">
<div class="alert alert-warning" v-show="showError" >
<button type="button" class="close" @click="hideMessage()">X</button>
<strong>Error!</strong>
</div>
<h1>Create a Todo</h1>

<div class="info-form">
<form>
<div class="form-group">
<label for="name">Todo name</label>
<input v-model="todo.name" type="text" class="form-control" id="name" aria-describedby="nameHelp" placeholder="Enter Name">
<small id="nameHelp" class="form-text text-muted">Enter your todo's name</small>
</div>
</form>

<button class="btn btn-primary" v-if="!this.todo.id" @click="createTodo()" ><span>Create</span>
<button class="btn btn-primary" v-if="this.todo.id" @click="updateTodo()" ><span>Update</span></button>

<button class="btn btn-primary" @click="newTodo()" >New..</button>
</div>
</div>
</div>
</div>
</template>
<script>
import {APIService} from '../APIService';

const apiService = new APIService();

export default {

name: 'CreateTodo',

components: {
},

data() {
    return {
        showError: false,
        todo: {}
    };

},

methods: {
createTodo(){
apiService.createTodo(this.todo).then((result)=>{

console.log(result);
if(result.status === 201){
    this.todo = result.data;
}
},(error)=>{

    this.showError = true;

});
},
updateTodo(){
apiService.updateTodo(this.todo).then((result)=>{
    console.log(result);
},(error)=>{
    this.showError = true;
});
},
newTodo(){
    this.todo = {};
}
},

mounted() {
if(this.$route.params.pk){
    apiService.getTodo(this.$route.params.pk).then((todo)=>{
    this.todo = todo;
})
}
},
}
</script>
<style scoped>
.aform{
margin-left: auto;
width: 60%;
}
</style>

Listing Todos

Open components/ListTodo.vue and add the following content:

<template>
<div>
<h1>Todos ()</h1>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>

<tr v-for="todo in todos" @click="selectTodo(todo)">

<th></th>

<td></td>

<td>
<button class="btn btn-danger" @click="deleteTodo(todo)"> X</button>
<a class="btn btn-primary" v-bind:href="'/todo-update/' + todo.id"> &#9998; </a>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {APIService} from '../APIService';
const API_URL = 'http://localhost:4000';

const apiService = new APIService();

export default {

name: 'ListTodo',

components: {
},

data() {

return {

todos: [],
numberOfTodos:0
};

},

methods: {

getTodos(){
apiService.getTodos().then((data) => {

this.todos = data.data;
this.numberOfProducts = data.count;

});
},
deleteTodo(todo){

apiService.deleteTodo(todo).then((r)=>{



if(r.status === 204)
{


alert("Todo deleted");

this.$router.go()

}

})

},
},

mounted() {

this.getTodos();

},

}

</script>

<style scoped>

.list-horizontal li {

display:inline-block;

}

.list-horizontal li:before {

content: '\00a0\2022\00a0\00a0';

color:#999;

color:rgba(0,0,0,0.5);

font-size:11px;

}

.list-horizontal li:first-child:before {

content: '';

}

</style>

Adding the API Service

import axios from 'axios';
const API_URL = 'http://localhost:8000';

export class APIService{

constructor(){
}

getTodos() {

const url = `${API_URL}/api/todos/`;

return axios.get(url).then(response => response.data);
}
getTodo(pk) {

const url = `${API_URL}/api/todos/${pk}`;

return axios.get(url).then(response => response.data);

}

deleteTodo(todo){

const url = `${API_URL}/api/todos/${todo.pk}`;
    return axios.delete(url);
}

    createTodo(todo){
    const url = `${API_URL}/api/todos/`;
    return axios.post(url,todo);
}

updateTodo(todo){
const url = `${API_URL}/api/todos/${todo.pk}`;
return axios.put(url,todo);
}
}

Conclusion

In this tutorial, we've created a CRUD application with Node.js and Vue which consumes a REST API created with Express.

Note: We also publish our tutorials on Medium and DEV.to. If you prefer reading in these platforms, you can follow us there to get our newest articles.

You can reach the author via Twitter:

About the author

Ahmed Bouchefra
is a web developer with 5+ years of experience and technical author with an engineering degree on software development. You can hire him with a click on the link above or contact him via his LinkedIn account. He authored technical content for the industry-leading websites such as SitePoint, Smashing, DigitalOcean, RealPython, freeCodeCamp, JScrambler, Pusher, and Auth0. He also co-authored various books about modern web development that you can find from Amazon or Leanpub


Get our Learn Angular 8 in 15 Easy Steps ebook in pdf, epub and mobi formats, plus a new Angular 8 tutorial every 3 days.


Online Courses (Affiliate)

If you prefer learning with videos. Check out one of the best Angular courses online
Angular 8 - The Complete Guide (2019+ Edition)

Angular Crash Course for Busy Developers

comments powered by Disqus
DMCA.com Protection Status