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;
- get,
- post,
- put,
- delete
RESTful requests.
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
// ./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;