Podcast Title

Author Name

0:00
0:00
Album Art

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

By 10xdev team July 09, 2018
Listen

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.

Join the 10xdev Community

Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.

Recommended For You

Up Next