Link For Discussion/Doubts: Discuss any doubts on this page
- HTML
- CSS
- JavaScript
- A little familiarity with the Terminal/Powershell/Command Prompt
- Node.js (version > 10)
- DB
- Create an account with mLab (https://mlab.com)
- Verify your email
- On the dashboard, click on Create New
- Create a SANDBOX [Free] version DB, it's awesomely free!
- Choose any region
- Enter a name
- Complete the order
- Click on the db name to get the URI
- Also, add a user by clicking on the user tab on the same page, this user will be used to access the db
- OR Install MongoDB CE
- Create an account with mLab (https://mlab.com)
- VS Code (this will be our editor environment (IDE))
- Download the folder/repository (or clone it if you know git)
- Open the folder in VS Code using 'Open Folder' from File in the top main menu
- Start Terminal from Terminal > New Terminal (in main menu)
- In the Terminal, run
npm install
Now you have almost your libraries setup and the project is ready to be run - You can check the list of libraries which have been installed in the file ==package.json==
- GOTO ==config/mongoose.js== and add your mLab db uri near [TODO 1], replacing and
- GOTO ==index.js==, Study the comments starting with [READ]
- In the Terminal, run
node index.js
- You can kill the server with ctrl + c
- In the Terminal, run
npm install nodemon
- Now you can run the server with
nodemon index.js
, this will restart the server everytime the code changes in js files
-
In the terminal, run
npm install ejs
to install our template engine (we'll come to what that is soon!) -
GOTO ==index.js==
-
Replace [TODO 1] with
app.use('/', require('./routes/index'));
-
GOTO ==routes/index.js== and replace [TODO 1] with
router.get('/', function(req, res){ res.end('I Am Iron Man'); });
-
GOTO ==index.js== and replace [TODO 2] with
app.set('view engine', 'ejs');
This tells our express app to use the 'ejs' library as our template or view engine
-
GOTO ==routes/index.js== and modify the code in the step 4. to look like:
router.get('/', function(req, res){ res.render('home'); });
This basically finds the file ==home.ejs== in folder ==views== and converts it to html and sends it back to the browser
-
Since we've already created 2 controller files viz. ==controllers/events_controller.js== and ==controllers/registrations_controller.js==, we export some methods from them and use them in routes
-
In the last coding step (previous section) in ==routes/index.js==, replace this part
router.get('/', function(req, res){ res.render('home'); });
with this
router.get('/', eventsController.home);
It does the same thing, it's just that our code is a little more distributed right now + notice the title: "GDG Events Home" part! It is called context
-
GOTO ==views/home.ejs== and replace [TODO 1] with
<%= title %>
-
GOTO and explore ==config/mongoose.js==. It has used mongoose package to connect to MongoDB
-
GOTO ==index.js== and replace [TODO 4] with
const db = require('./config/mongoose');
-
MongoDB requires the data to be stored in JSON format (it's like a hash/dictionary in programming terms). We need to create schema (predefined formats) to specify what fields do we want to store for each entity (called collections). Here we have 2 entities
- Event
- Registration
-
One Event can have Many Registrations OR we can say, Many Registrations can belong to One Event
-
GOTO & explore ==models/event.js== and ==models/registration.js==
-
Advantage of mongoose.js is that it is an ORM (a layer between express server and MongoDB) and makes our interaction with MongoDB (reading, writing, updating, deleting) quite easy without having to get into the details of learning the syntax for MongoDB.
-
GOTO and explore the different HTML elements in ==views/home.ejs== The form has inputs and text areas for 3 fields for **title, description and date **
-
GOTO ==views/home.ejs== and near [TODO 2], add the following to the form's action attribute
/events/create
(this will be the route or url to which we will be sending the data from the form)
-
GOTO ==controllers/events_controller==, replace [TODO 2] with
const Event = require('../models/event');
This will import the schema for Event to be used to create and read events
-
GOTO ==controllers/events_controller== and replace [TODO 3] with the following code, to receive data and create an event
module.exports.createEvent = function(req, res){ console.log(req.body); Event.create({ title: req.body.title, description: req.body.description, date: req.body.date }, function(err, event){ if (err){ console.log('Error in creating an event'); } console.log('Event Created : ', event); return res.redirect('/'); }); }
We have created and exported a function which will create an event using create() method given by mongoose. It is taking the first argument as the fields of the event and the second argument as the callback function which receives an error (if event could not be created) and the event (if it is created and saved in the db)
-
GOTO ==routes/index.js== and replace [TODO 2] with
router.post('/events/create', eventsController.createEvent);
Here, '.post' is the HTTP method used to send data to the server when we need to create something/make some changes into the database
-
Run and check if the event is getting created (it should print in the terminal where server is running)
-
GOTO ==controllers/events_controller.js== and replace the code inside action home with
Event.find({}, function(err, events){ if (err){ console.log('error in finding events'); } return res.render('home', { title: "GDG Events Home", events: events }) });
Here we are fetching all the events from the database (again using a function provided by mongoose) and passing them to the context of the views
-
GOTO ==views/home.ejs== and replace [TODO 2] with
<div id="events-list-container"> <ul> <% for (event of events){ %> <li> <div> <h3><%= event.title %></h3> <% if (event.date){ %> <p><%= event.date.toLocaleString() %></p> <%}%> <%= event.registrations.length %> Registrations <p><%= event.description %></p> </div> </li> <% } %> </ul> </div>
Here, as you can see, we are looping around the list of events passed in the context (from the last step) and displaying the details (it looks just like simple JavaScript, we just need to wrap variables accessed by <%= %> whenever a value needs to be printed)
- An API is basically a medium of communication using JSON. When the code is divided into 2 parts, viz. Front End (examples: Android, Angular, iOS) and Back End (examples: Node.js/Python/Ruby server), the communication is done using APIs
- Front End holds the code for design (how the page looks)
- Back End holds the logic of sending data according to the user (example Indian users might see different news and USA users would see news relevant to them OR you and your neighbour might look a the same design of Facebook, but would see different feeds and friends list)
- Let's create an API for sending data about the list of events and their registrations to the Front End
- GOTO ==controllers/events_controller.js== and replace [TODO 4] with
module.exports.eventsList = function(req, res){ Event.find({}, function(err, events){ if (err){ console.log('error in finding events'); } return res.json(events); }); }
- Finally, create a route for this action above. GOTO ==routes/index.js== and replace [TODO 3] with
router.get('/api/events/', eventsController.eventsList);
- Run and check if the API works
- Some links (look out for documentation in each)
- Mongoose: https://mongoosejs.com/
- Express.js: https://expressjs.com/
- Node.js: https://nodejs.org/en/
- MongoDB: https://www.mongodb.com/