Building a Store with Vue – Part Nine : Express Routes & Controllers

In this part nine we are going to discuss how to set up backend routes and controllers, but before we start let me get a few things out of the way.

Backend Choice

There are many ways to build a backend and to deal with data in a Dashboard. You could use WordPress, Laravel, Rails, Django and so on. We often use Laravel and Vue. You could however also use Express.js and that we are doing here for this Vue/JS Store running on Node. We use Express to set things up.

Vue Router vs Express Confusion

Just to get the confusion out of the way on why we are using Express here for the backend and not Vue router as some of you might be wondering here a quote from Reddit user Piper

Normally, on a typical website, when a new page is requested, the browser loads the new URL from scratch. This means it talks to your backend, and loads a new page. If your backend was running on Express, that would be doing the heavy lifting.

However, when front end frameworks get involved, the system changes. The beauty of frameworks such as Vue means that the URLs are completely handled by the front end. That means the browser doesn’t necessarily need to make any new requests — it can just load the new page and change the URL via JS. That’s what vue-router does.

Sometimes, you want to fetch data when a new page is loaded. Vue handles the route change, then you can tell it to query a backend for some data. REST APIs are great for this — and Express is a great framework for those. Keep in mind, it doesn’t matter how the data gets to the front end, just that it does. So as long as your backend provides the right data at the right API endpoints, you can use whatever backend framework or language you want. In this architecture, the backend and front end are completely separated.

https://www.reddit.com/r/webdev/comments/6aiw4d/vuejs_vs_express/

Routes

Now let’s talk about routes and controllers. We begin with importing express and setting it as a constant router. Then we do a REST GET request using the router object:

// ./routes/index.js
const express = require('express');
const router  = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'App running' });
});

module.exports = router;

The router object is a utility method that is built on top of express to make RESTful APIs even easier. https://scotch.io/courses/build-an-online-shop-with-vue/routes-and-controllers

API Routes

Now, to actually get and put data using Express’ REST API we use:

// routes/api/index.js
const express                = require('express');
const router                 = express.Router();
const productController      = require('../../controllers/product')
const manufacturerController = require('../../controllers/manufacturer')

router.get('/manufacturers', manufacturerController.all);
router.get('/products', productController.all);
router.get('/products/:id', productController.byId);
router.post('/products', productController.create);
router.put('/products/:id', productController.update);
router.delete('/products/:id', productController.remove);

module.exports = router;
And the Route Object provides
  • get,
  • post,
  • put,
  • delete

RESTful requests.

NB In Laravel I would be using Axios for this
NBB Also do notice the :id for dynamic operations using the product id as an argument.

Controllers

Currently ESLint is balking the controllers are not there yet and that is correct. So the routes above lead to nowhere. So let’s add the directory and the actual files shall we?

Manufacturer Controller

Here we start with importing the Models and then we move on to the manufacturer controller specifics.

// ./controllers/manufacturer

const Model = require('../model');
const {Product, Manufacturer} = Model;

const manufacturerController = {
    all (req, res) {
      // Returns all manufacturers
        Manufacturer.find({})
            .exec((err, manufacturers) => res.json(manufacturers))
    }
};

module.exports = manufacturerController;
  • require can be turned into ES6 export but we left it be for now.
  • module.exports used to make manufacturerController available for other parts of our backend.

Product Controller

And for the product details itself we have this large controller. Again we bein with importing the model and setting some constants to use. Then we start with the actual Product Controller:
// ./controllers/product.js

import Model from '../models';

const { Product, Manufacturer } = Model;

const productController = {

all(req, res) {

Product Display

Once this is done we need to return the products for display with information from the producers:

// Returns all products

Product.find({})

// alongside it's manufacturer
// information

.populate('manufacturer')

.exec((err, products) => res.json(products));

},

byId(req, res) {

constidParam=req.params.id;

Single Product Display

And for showing a single product we have:

// Returns a single product
// based on the passed in ID parameter

Product

.findOne({ _id: idParam })

// as well as it's manufacturer

.populate('manufacturer')

.exec((err, product) => res.json(product));
},

Product Creation

New Product Creation starts here with the create function

create(req, res) {
const requestBody = req.body;

// Creates a new record from a submitted form

const newProduct = newProduct(requestBody);

// and saves the record to
// the database

new Product.save((err, saved) => {

// Returns the saved product
// after a successful save

Product
.findOne({ _id: saved._id })
.populate('manufacturer')
.exec((err, product) => res.json(product));
});
},

Product Update

Updating the product we do with the Update function

update(req, res) {

constidParam=req.params.id;

let product=req.body;

// Finds a product to be updated
Product.findOne({_id:idParam }, (err, data) => {

Updating the product we do using the data property

// Updates the product payload

data.name=product.name;
data.description=product.description;
data.image=product.image;
data.price=product.price;
data.manufacturer=product.manufacturer;

Product Storage

To store the product we use this function:

// Saves the product

data.save((err, updated) =>res.json(updated));
});
},

Deleting a Product

And last but not least the product removal function

remove(req, res) {
constidParam=req.params.id;

// Removes a product
Product.findOne({ _id:idParam }).remove((err, removed) =>res.json(idParam));
},
};

export default productController;

 

Jasper Frumau

Jasper has been working with web frameworks and applications such as Laravel, Magento and his favorite CMS WordPress including Roots Trellis and Sage for more than a decade. He helps customers with web design and online marketing. Services provided are web design, ecommerce, SEO, content marketing. When Jasper is not coding, marketing a website, reading about the web or dreaming the internet of things he plays with his son, travels or run a few blocks.