AppDividend
Latest Web Development Tutorials

VueJS Nodejs Tutorial

Vue.js 2.0 Nodejs Tutorial

7,228

VueJS 2.0 Nodejs Tutorial is today’s main topic. NodeJS is a viral platform nowadays because of its features and Express is a web framework build on top of Node.js. This is the perfect example of  How to use VueJS with NodeJS.

Summary

VueJS Nodejs Tutorial walks through creating a Node.js, MongoDB, Express, and front-end framework (Vue.js) application. Client side code is bundled with Webpack. It is also called VueJS NodeJS Express Tutorial or Vue Express Example Tutorial.

Purpose

One possible reason I am writing this is showcase how Node.js, Express Framework, MongoDB and modern client-side Javascript frameworks (Vue.js with Webpack) can all play nicely together. Express is still the dominant Node.js web framework.

The App and Stack

This application is capable of Creating, Reading, Updating and Deleting items from the MongoDB database and It’s relatively simple Single Page Application. So It’s a CRUD application with VueJS, NodeJS, MongoDB, and Express. We are using MongoDB database so it is Vuejs with MongoDB Tutorial Stack.

Vue.js 2.0

For learning Vue.js, I suggest to my this article Vuejs Tutorial With Example. It will guide you to learn fundamentals of Vue.js 2.0. If you want to know how a router works on Vue.js, then check out my this tutorial How To Use vue-router in VueJS.

Setup an Application Environment

Step 1: Make a directory of VueJS Nodejs Tutorial Project.

Create one project folder called by the following command.

mkdir VueJSNodePro

Go into that folder, create one file called package.json file and in that copy this code into it.

{
  "name": "vuenodepro",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "axios": "^0.16.2",
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-3": "^6.24.1",
    "babel-runtime": "^6.25.0",
    "css-loader": "^0.28.4",
    "file-loader": "^0.11.2",
    "vue": "^2.4.2",
    "vue-router": "^2.7.0",
    "vue-axios": "^2.0.2",
    "vue-loader": "^13.0.2",
    "vue-template-compiler": "^2.4.2",
    "webpack": "^3.4.1",
    "webpack-dev-server": "^2.6.1"
  }
}




Type the following command in your terminal.

npm install

It will download the all the required development dependencies in our project.

Next step would be to configure our webpack development server. So create one file called webpack.config.js in project’s root and put the following code in it.

// webpack.config.js

module.exports = {
  // This is the "main" file which should include all other modules
  entry: './src/main.js',
  // Where should the compiled file go?
  output: {
    filename: 'bundle.js'
  },
  resolve: {
  alias: {
    vue: 'vue/dist/vue.js'
  }
},
  module: {
    // Special compilation rules
    loaders: [
      {
        // Ask webpack to check: If this file ends with .js, then apply some transforms
        test: /\.js$/,
        // Transform it with babel
        loader: 'babel-loader',
        // don't transform node_modules folder (which don't need to be compiled)
        exclude: /node_modules/
      },
      {
        // Ask webpack to check: If this file ends with .vue, then apply some transforms
        test: /\.vue$/,
        // don't transform node_modules folder (which don't need to be compiled)
        exclude: /(node_modules|bower_components)/,
        // Transform it with vue
      use: {
        loader: 'vue-loader'
      }
    }
  ]
},
devServer: {
       port: 3000
   }
}

Webpack will create one bundle.js file in a root. This file is the ES5 version of JavaScript, and it will be included in our index.html file. Create one file called index.html in a root folder.

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>VueJS NodeJS and Express example</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
    <div id="app"></div>
    <script src="bundle.js"></script>
  </body>
</html>

Step 2: Create sub folders and main.js file.




Now, create one folder called src because all of our components will be stored in this folder. In that folder create one javascript file called main.js.

// main.js

import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

const router = new VueRouter({ mode: 'history' });
new Vue(Vue.util.extend({ router })).$mount('#app');

I have imported vue, vue-router, and vue-axios library from the node_modules folder. The vue-router library is for routing our components where a vue-axios library is to send HTTP request to the server.

Next, create one vue component inside src folder called App.vue.

// App.vue

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

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

<script>

    export default{
    }
</script>

In this component, I have defined router-view tag. It simply our application’s container part. All the different components will be rendered in this <router-view></router-view> element.

We need to include this App.vue file in our main.js and pass the argument while creating a vue instance.

// main.js

import App from './App.vue';

new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Step 3: Make components folder and create sub components.

Create one folder inside src folder and name it components. In components folder, create one file called CreateItem.vue.

// CreateItem.vue

<template>
  <div>
    <h1>Create An Item</h1>
    <form>
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            <label>Item Name:</label>
            <input type="text" class="form-control" v-model="item.name">
          </div>
        </div>
        </div>
        <div class="row">
          <div class="col-md-6">
            <div class="form-group">
              <label>Item Price:</label>
              <input type="text" class="form-control col-md-6" v-model="item.price">
            </div>
          </div>
        </div><br />
        <div class="form-group">
          <button class="btn btn-primary">Add Item</button>
        </div>
    </form>
  </div>
</template>
export default {
    data(){
        return{
          item:{}
        }
    },
    methods: {
      addItem(){

      }
}

Import this CreateItem.vue component inside the main.js file. We will need this component for routing purpose.

Switch to the main.js file and import this component by the following code.

import CreateItem from './components/CreateItem.vue';

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

// main.js

const routes = [
  {
        name: 'CreateItem',
        path: '/',
        component: CreateItem
    }
];

Register this array in the time of the creation of router object.

// main.js

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

Now, start the server by the following command.

npm start

Switch to this URL: http://localhost:3000. You will see the Create Form like below.

 

MEVN Stack ApplicationStep 4: Configure NodeJS Express MongoDB backend.

Next step, would be to create Node.js and Express backend to store the data. Create one file in the project root called server.js

Now, we need to install the express framework and other dependencies via NPM, so let us do it first.

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

Switch to newly created server.js file and enter the following code in it.

// server.js

var 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);
      });

Next thing is we need to create the MongoDB database and connect it with our express application.

Note: You need to have installed MongoDB database on your server or local otherwise first you need to download it and start the MongoDB server.

Create one config folder inside project root. In that create one file called DB.js.

// DB.js

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

Import this file into our server.js file and use mongoose to set up a database connection with MongoDB. You need to copy the whole server.js file; I am about to show 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);
       });

Step 5: 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.

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 expressRouter folder, create one file called itemRoutes.js.

// 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 routes related to CRUD application.



This file will be included in our server.js file.

// server.js

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

app.use('/items', itemRoutes);

Step 6: Insert the value in the MongoDB.

So, your final server.js file will look like this.

// server.js

const express = require('express'),
      path = require('path'),
      bodyParser = require('body-parser'),
      cors = require('cors'),
      mongoose = require('mongoose'),
      config = require('./config/DB'),
      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);
      });

From the front end side, we need to set up axios and fire up the HTTP Post call to the NodeJS server.

// CreateItem.vue

addItem(){
        let uri = 'http://localhost:4000/items/add';
        this.axios.post(uri, this.item).then((response) => {
          console.log(response)
        })
    }

If your all the MongoDB database configuration is correct then, you will be able to store the values in the database.

 

VueJS and Express CRUD Application

Step 7: Display the items.

Now, we need to route to the listing of the item, when we got the response. Create one component inside components folder called DisplayItem.vue.

// DisplayItem.vue

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

        <div class="row">
          <div class="col-md-8"></div>
          <div class="col-md-4">
            <router-link :to="{ name: 'CreateItem' }" class="btn btn-primary">Create Item</router-link>
          </div>
        </div><br />

        <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">
                    <td>{{ item._id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td></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>

Now, we need to include this component to our main.js file, and also we need to register this component’s route in the routes array. I am writing the whole file, so just need to copy this file into your file.

// main.js
import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

import App from './App.vue';
import CreateItem from './components/CreateItem.vue';
import DisplayItem from './components/DisplayItem.vue';

const routes = [
  {
        name: 'CreateItem',
        path: '/create/item',
        component: CreateItem
    },
    {
          name: 'DisplayItem',
          path: '/',
          component: DisplayItem
      }
];

const router = new VueRouter({ mode: 'history', routes: routes });
new Vue(Vue.util.extend({ router }, App)).$mount('#app');

You can notice here that,  I have changed the routes name and root route would be the listing of the items page, so when you hit this URL: http://localhost:3000. It will display like this.

VueJS and mongodb

Step 8: Generate EditItem.vue component.

Now, we need to create one more component inside components folder called EditItem.vue.

// EditItem.vue

<template>
    <div>
        <h1>Update Item</h1>
        <div class="row">
          <div class="col-md-10"></div>
          <div class="col-md-2"><router-link :to="{ name: 'DisplayItem' }" class="btn btn-success">Return to Items</router-link></div>
        </div>

        <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 name="product_price">Item Price</label>
                <input type="text" class="form-control" v-model="item.price">
            </div>

            <div class="form-group">
                <button class="btn btn-primary">Update</button>
            </div>
        </form>
    </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: 'DisplayItem'});
                });
            }
        }
    }
</script>

Now, we need to import this component into a main.js file.

// main.js

import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

import App from './App.vue';
import CreateItem from './components/CreateItem.vue';
import DisplayItem from './components/DisplayItem.vue';
import EditItem from './components/EditItem.vue';

const routes = [
  {
        name: 'CreateItem',
        path: '/create/item',
        component: CreateItem
    },
    {
          name: 'DisplayItem',
          path: '/',
          component: DisplayItem
      },
      {
            name: 'EditItem',
            path: '/edit/:id',
            component: EditItem
        }
];

const router = new VueRouter({ mode: 'history', routes: routes });
new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Also, we need to update DisplayItem.vue file.

// DisplayItem.vue

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

        <div class="row">
          <div class="col-md-10"></div>
          <div class="col-md-2">
            <router-link :to="{ name: 'CreateItem' }" class="btn btn-primary">Create Item</router-link>
          </div>
        </div><br />

        <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">
                    <td>{{ item._id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td><router-link :to="{name: 'EditItem', 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>

Now, if you return to the browser and note that, if your webpack development server and your node server is not running, then please start your server at URL: http://localhost:3000.

If you have created more than one item then, you will see something like this. DisplayItem.vue

vue express mongodb

EditItem.vue will look like this.

VueJS CRUD

Follow my blog with Bloglovin

This tutorial VueJS Nodejs Tutorial is now over. 

Download Project On Github

Steps:

1) Clone the repository.
2) type the following command in your project root directory: npm install.
3) You need to install MongoDB database and also start the server of MongoDB.
4) Go to the project folder >> config >> DB.js file and change the URI according to your database connection and credentials. : Start the server: npm start.
5) webpack development server will start at http://localhost:3000
6) You also need to initiate the NodeJS server by typing following command: nodemon server.

If you still have any doubt then ask in a comment below, I am happy to help you out.

 

10 Comments
  1. Miodrag says

    Thanks man!
    I am using vuejs and mongodb, but with Laravel.
    Will try this combination, looks promising!

    1. Krunal says

      Go ahead!! Keep experimenting.

  2. Painache says

    Thanks bro, you helped me a lot.
    Wish you write more tuts about nodejs and vuejs.

    1. Krunal says

      Thanks man!!

  3. ray says

    great tutorial!!!!!

  4. Kul says

    After a long search finally got this page !!! The best and working solution so far. Good work Krunal !!

  5. Greg says

    Hi. Krunal!
    I think this tutorial is very educating and helpful.
    But I have a problem when run site:
    bundle.js:4365 GET http://localhost:4000/items net::ERR_CONNECTION_REFUSED
    What can it be?
    Thanks!

    1. Krunal says

      I guess your port is already consumed by other process, please change it to the other, or kill other processes.

  6. Greg says

    Thank you for the response, Krunal.
    I checked with netstat but didn’t find such process.
    I will continue research, thank you very much.

  7. Igor says

    Hi, Krunal,

    Your tutorial is great, but you forgot one thing. You forgot to say that we need to run nodemon(node) server.js. Without that, we can’t run any server script and connect with database.

    Sincerely,

    Igor

Leave A Reply

Your email address will not be published.