Pt3 Building a food order system with MEAN Stack (MongoDB, Express, AngularJs and NodeJs).
In our Last tutorial, we started by creating the model of our users, we also explained the concept of token based authentications with passport and Jwt
token. Not forgeting, Our routes, controller, and model for the user was put in place along with the authentication mechanism for the user controller.
Overview.
Now we have our user model ready, in this installment, we are going to add some new methods and function for our users. We are alsso going to create our item model Route and some controller method.
Requirement.
- Typescript version 2.4.2
- Node version version 8.9.4
- Npm version 5.6.0
- Express version ^4.15.3.
- Postman
- Voltron Server Repository
Table of content.
- Adding New methods to the user controller.
- Creating the Item model.
- Creating the item Routes and Controller.
- Adding methods to the Item Controller.
Difficulty
This tutorial is rated intermediate.
Adding New methods to the user controller.
If you remember, in our Last tutorial, we created some end-points for our users which request can be sent to from our front-client. If you can remember, we added to endpoints;
- The End-point to Create a User.
- The End point to Authenticate a user with
JWT token
.
What End-points would be added? yeah, i remember we are to add three Endpoints
- The End point to get a single user from the
db
- The End point to get all users.
- Lastly the point to update any property in the users' Object.
Lets Start withe End-point responsible for return a single item from the database.
Its quite simple, all we need to do is find a unique identifier in the database like id
, username
and email.
The End point to get a single user from the db
public static async getUser(req: Request, res: Response, next: NextFunction) {
try {
//
// Get data
const username: String = req.params.username;
let result = await UserModel.findOne({ username }).exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'Successfull got a user',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not get Examples',
err: err
});
}
}
In the above, we are using the asyc
and await
to wait for the actual data it arrive. We are simply just hoping the data will arrive. This is what is called asyncronous. We get the user input (username), used the username to find through the model for the said user and return the response. If an error occur, return the message
in the catch block.
The End-point to get all users.
The End-point to get all users is almost thesame as the one for a single user. the differnce is the method used on the user model. The method on the model is find()
.
exec()
returns a promise when the find()
methodis ran on the UserModel.
public static async getAll(req: Request, res: Response, next: NextFunction) {
try {
//
// Get data
let result = await UserModel.find().exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'it works! We got all users',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not get Users',
err: err
});
}
}
/**
* getUser
* @param {*} req
* @param {*} res
* @param {*} next
*/
The response area simply checks for code for error and respond according.
The End-point to update any property in the users' Object.
Finally on our UserController, lets work on the update method to change any value on the UserModel or object. We are going to be making use of the object spread operator for object object simple by adding to the object.
Firstly we search for the user usinng the request from the body of what was entered by the user, of which was the username of the user, next we use use spread object operator to to update the model with what was entered from the user request body.
Note: The method for updating on the model is findOneAndUpdate()
it accepts the parameter that can be used to find an item in the model.
const username: String = req.params.username;
let result = await UserModel.findOneAndUpdate({ username }, {
...req.body,
updatedAt: new Date()
}).exec();
Okay we updated the object, we can now save the status code and respond with the status code showing an appropriate message.
try {
//
// Get data
const username: String = req.params.username;
let result = await UserModel.findOneAndUpdate({ username }, {
...req.body,
updatedAt: new Date()
}).exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'Sucessfully updated a user',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not create the user',
err: err
});
}
}
Finally all our user methods are implemented in the UserController.
Before we forget lets add the route for our new UserController method.
Go to api/user/user.route.ts
and Update the the route file.
import { Router, Request, Response, NextFunction } from 'express';
import UserController from './user.controller';
export class UserRouter {
public router: Router
/*-------- Constructor --------*/
constructor() {
//
// Set router
this.router = Router();
this.init();
}
/*-------- Methods --------*/
/**
* Init all routes in this router
*/
init () {
this.router.put('/:username', UserController.update);
this.router.get('/', UserController.getAll);
this.router.get('/:username', UserController.getUser);
this.router.post('/', UserController.create);
this.router.post('/authenticate', UserController.authenticate);
}
}
//
// Create Router and export its configured Express.Router
// new UserRouter().init();
export default new UserRouter().router;
Noticed in the init method, we added some new route which uses different protocol.
which are PUT
and GET
.
Building the Item model.
We just finished the whole UserController. Next up is the items, so what does the item need?
The item model needs the followng property
- id
- title
- type
- desc
- price
- photo
- inStock
- createdAt
- updatedAt
- deletedAt
id ---The id is generated by the mongodb and its unique for each item, which is an object
title--- The title of the item e.g Fried Rice, wwhich accepts a string
type--- The type which is a string e.g drink, food
desc--- This accepts a string and shows a short discription of the food.
photo--- This accepts a string, which shows the location of the image in the pubic or assets folder.
inStock--- This is the number of item avialable at a given time, its accepts the type number.
createdAt--- This is the exact time an item was inserted into the db
it accepts a type of Date
updatedAt--- The exact time an item in the db
was modified.
deletedAt --- As it implies.
In api/item
, create a file called item.model.ts and add the code for building the model.
import { Schema, model } from 'mongoose';
let ItemSchema: Schema = new Schema({
id: {
type: Number,
},
title: {
type: String,
required: true,
unique: true
},
type: {
type: String,
required: true,
default: ''
},
desc: {
type: String,
default:'',
},
price: {
type: Number,
required: true
},
photo: {
type: String,
default: ''
},
inStock: {
type: Number,
default: 0,
required: true
},
createdAt: {
type: Date,
default: new Date
},
updatedAt: {
type: Date,
default: new Date
},
deletedAt: {
type: Date,
},
});
export default model('Item', ItemSchema);
As usual, we import schema
and model from mongoose in line 1.
and export the model at the last line.
hTake note: On the Schema, we have some prroperties like dafault
and required. these are used to prefill and validate the entry to the db
respectively.
Building the item Route.
Firstly, we need to create the prefix for our route in the main routes.ts
file which is found on the config
folder.
update the setAllRoutes method
private setAllRoutes() {
this.app.use('/api/users', UserRouter);
this.app.use('/api/items', ItemRouter);
}
Now we have a prefix for our item route called localhost/api/items/
.
Next up the item.route.ts
, create this file in the api/item
if not created.
Here, we need to add all the routes for initiating actions for our controller with different protocol.
import { Router, Request, Response, NextFunction } from 'express';
import ItemController from './item.controller';
export class ItemRouter {
public router: Router
/*-------- Constructor --------*/
constructor() {
//
// Set router
this.router = Router();
this.init();
}
/*-------- Methods --------*/
/**
* Init all routes in this router
*/
init () {
this.router.put('/:_id', ItemController.updateItem);
this.router.get('/', ItemController.getAll);
this.router.get('/:_id', ItemController.getItem);
this.router.post('/', ItemController.createItem);
this.router.delete('/:_id', ItemController.deleteItem);
}
}
//
// Create Router and export its configured Express.Router
// new UserRouter().init();
export default new ItemRouter().router;
The first line import { Router, Request, Response, NextFunction } from 'express';
imports all the modules listed in the curly brace from express. We also imported our itemController which we have not created yet.
In the constructor method, we are instantiated a new router, and an init() method that kicks up very route.
Lets talk about the route in the init method.
this.router.put('/:_id', ItemController.updateItem);
The above route would show something like localhost:3000/api/items/12sdfffcvgfddszd
which uses the PUT
protocol to update an item property in the db
it uses the itemController method updateItem
for the logic, where 12sdfffcvgfddszd
is the id
of the item in the db
.
this.router.get('/', ItemController.getAll);
this.router.get('/:_id', ItemController.getItem);
The above two routes uses the GET
protocol to retrieve data from the db
the first route localhost:3000/api/item
uses the getAll method of the itemController to show all item in the db
.
while the second, also uses the get protocol but uses the id
of the item to return a particular item.
this.router.post('/', ItemController.createItem);
this.router.delete('/:_id', ItemController.deleteItem);
The first route this.router.post('/', ItemController.createItem);
uses the post
protocol to add items to the db
and it uses the method createItem while the last uses the id
to filter through the db and uses the DELETE
protocol to remove an item from the db.
Building the itemController.
We have been using methods and imported a controller that did not yet exist, so lets create the item controller and its methods.
Create the file item.controller.ts
in api/item
folder and add the code below.
import { Request, Response, NextFunction } from 'express';
import Model from './item.model';
export default class UserController {
/**
* Get all
* @param {*} req
* @param {*} res
* @param {*} next
*/
public static async getAll(req: Request, res: Response, next: NextFunction) {
try {
//
// Get data
let result = await Model.find().exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'it works! We got all items',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not get items',
err: err
});
}
}
/**
* getUser
* @param {*} req
* @param {*} res
* @param {*} next
*/
public static async getItem(req: Request, res: Response, next: NextFunction) {
try {
//
// Get data
const id: String = req.params._id;
let result = await Model.findOne({ id }).exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'Successfull got an item',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not get item',
err: err
});
}
}
/**
* Create
* @param {*} req
* @param {*} res
* @param {*} next
*/
public static async createItem(req: Request, res: Response, next: NextFunction) {
const title:String = req.body.title;
const id:Number = req.body.id;
const type:String = req.body.type;
const desc:String = req.body.desc;
const photo:String = req.body.photo;
const price:Number = req.body.price;
const inStock:Number = req.body.inStock;
// Create model
let model = new Model({
id,
title,
type,
desc,
photo,
price,
inStock
});
//
// Save
await model.save();
res.send({
message: 'Created!',
model: model
});
}
public static async deleteItem(req: Request, res: Response, next: NextFunction) {
const _id:String = req.params;
try {
//
// Get data
const username: String = req.params._id;
let result = await Model.findOneAndRemove({ _id }, {
...req.body,
deletedAt: new Date()
}).exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'Sucessfully deleted item',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not delete th item',
err: err
});
}
}
public static async updateItem(req: Request, res: Response, next: NextFunction) {
const _id:String = req.params;
try {
//
// Get data
const username: String = req.params._id;
let result = await Model.findOneAndUpdate({ _id }, {
...req.body,
updatedAt: new Date()
}).exec();
const status = res.statusCode;
//
// Response
res.send({
message: 'Sucessfully updated item',
result: result,
status: status
});
} catch (err) {
//
// Error response
res.send({
message: 'Could not create th item',
err: err
});
}
}
}
itemController Explaination.
We started by importing the item schema and Request, Response, NextFunction from express
we create the userController class and add the methods which we created on the routes. which are:
- getAll()
- getItem()
- createItem()
- deleteitem()
- updateItem()
Lets start with the getAll
method, which returns all the items in the db
using the find()
method on the item model.
We execute this code in a try and catch block and show the appropriate error from the model.
getItem method
This method uses the find() and accepts a property in the db, the id
of the object is used to find through the db
and return a specific item.
create item method.
sets all the input from the body( data entered by the user), validation is ran on the data and saved using the method model.save
update item method
Uses the method findOneAndUpdate() which accepts the _id
of the item that needs to be updated using the objected spread operator, the data from the body is save and updated.
let result = await Model.findOneAndUpdate({ _id }, {
...req.body,
updatedAt: new Date()
}).exec();
delete item method
The method uses findOneAnd Remove()
method from the db
and accepts the id
of the item and using the object spread operator the item need to be deleted from the body is initiated
let result = await Model.findOneAndRemove({ _id }, {
...req.body,
deletedAt: new Date()
}).exec();
Conclusion
We just concluded the users and the items end-points for all request to our server, in the next part, we would build the orders model controller and route and use postman for testing our request, stay tune.
Curriculum
- Building a food order system with MEAN Stack (MongoDB, Express, AngularJs and NodeJs). pt1
- Building a food order system with MEAN Stack (MongoDB, Express, AngularJs and NodeJs). pt2
Posted on Utopian.io - Rewarding Open Source Contributors
Thanks for the contribution.
Need help? Write a ticket on https://support.utopian.io.
Chat with us on Discord.
[utopian-moderator]
Hey @sirfreeman! Thank you for the great work you've done!
We're already looking forward to your next contribution!
Fully Decentralized Rewards
We hope you will take the time to share your expertise and knowledge by rating contributions made by others on Utopian.io to help us reward the best contributions together.
Utopian Witness!
Vote for Utopian Witness! We are made of developers, system administrators, entrepreneurs, artists, content creators, thinkers. We embrace every nationality, mindset and belief.
Want to chat? Join us on Discord https://discord.me/utopian-io