Fullstack Hub

[Count: 1]

In the previous part, we created the Contact Us page by using Angular reactive form, implemented the client-side validation and created DataService to send the user information from the Contact Us page to the server-side. In this part, we will implement the server-side code in Node.js to take the user information and email it to the admin.

Introduction

So in the previous part, we developed the Contact Us page and helping classes in Angular that is our client-side. In order to email the Contact Us page information, we need some server-side application that we are going to develop in this part using Node.js. 

There are a lot of Node.js tutorials available online so I don’t want to write redundant information, though I will briefly explain each step but its better reading some of the Node.js tutorials online before starting this article. 

Let’s Start

  1. Please go through previous parts before reading this one and download the part 3 from Github, this part already has the Node.js server-side project. You can just delete it if you want to follow along with me. 
  2. Once you clone/download part 3, open the project in Visual Studio Code, you would already have the mazharncoweb folder containing the Angular client-side project. Create a new folder name server on the same level as mazharncoweb
  3. In the bottom TERMINAL panel, write the command: cd server to get into new server folder, after that run command: npm init. It will ask you a couple of questions, enter the following answer to the required questions:
    1. Package Name: server
    2. Entry Name: mazharnco.js
    3. Leave the rest of the information or enter whatever you think is better.
    4. In the end, type yes for the question, Is this ok?
    5. So what we just did is created the package.json file in the server folder that will contain all references to our packages and entry point of our application. If you already worked in Node.js or read about it, you may know that Node.js itself is a quite slim library so we need to add a lot more packages to create our application. e.g. we will use Express.js framework that is used to create RESTful APIs in Node.js, nodemailer to send an email, etc.
  4. Next, let’s download all Node.js packages that we will use in our development and understand their purpose, open the bottom TERMINAL and run the commands on by one:
    1. npm install nodemailer --save : The nodemailer is used to send an email.
    2. npm install express --saveExpress.js is a node.js web application framework that we would use to write the RESTful APIs.
    3. npm install ejs --saveEJs is a template engine that works with Express.js, what it does to convert JavaScript into HTML and send it to the client, simple.
    4. npm install cors --save: To enable CORS. Since our client and server may be on different domain e.g. client can be on http://xyz.com and the server may be on http://abc.com. If a client wants to call any GET API or send data through POST API, this is normally not possible due to security reasons. CORS package makes it enable with our custom defined rules. 
    5. npm install body-parser --save: When we call POST API from a client like we are sending Contact Us information in the previous part, we are sending data in the request’s body, that only would be able to read in Express.js APIs by the body-parser package.
    6. npm install pm2 -gPM2 is a simple process manager to start, stop, restart, show a status of the Node.js application. We will use it for the same purpose and just like we learned environment-specific build for Angular application, here we will run Node.js application environment-wide. 
  5. Alright, hopefully, you have downloaded all required packages and now you have node_modules folder in your main folder server, now let’s start development. 
  6. First, let’s create the email.js file where we will write code to send an email. Create the new folder shared in the server folder, right-click on it, select the option New File, enter the file name email.js. Add the following code in it:
JS
  1. Pretty straightforward code, we are using nodemailer package that we have installed earlier if you go to their official website link, we are using code from there. The sendEmail is a function with to, optional bccsubj, msgHTML msg and the callback function. All are self-explanatory and if you read about Node.js, you would learn that Node.js function has the callback function, that is called when function execution is done, so this feature helps Node.js application to not wait for function completion and move the control to the next function. The nodemailer also supports callback, that’s why we are passing a callback function as a parameter so that when nodemailer is done sending an email, it returns us information in callback e.g. successful or failure response. We will write this callback function in contact with POST API. We will learn the complete flow when developing the contact POST function.
  2. The important thing you can see is the process.env, we will create environment file and run Node.js application with pm2 specifying that environment file so that it can replace process.env variables with the right environment values.
  3. Create a new folder model in the server folder, right-click on it and select New File, enter the name of the file as contactMdl.js. This would be our model class where we will have the same Contact Me form attributes with validation when we will use a MongoDB database. Right now, we will only have one function to send an email to the admin. Edit the contactMdl.js file and add the following code:
JS
  1. So in the first line, we are adding email.js reference we created in the previous step. We are creating a sendContactEmail function, exporting it so that it can be accessed. Here we are creating two kinds of messages, one is plain text whereas second is HTML so it can be accessed on both kind of devices who has HTML support and one who doesn’t. The last parameter is the callback function that we are sending as it is receiving from function parameters. The admin email address is loading from environment file that we would create in upcoming steps.
  2. Next, let’s create a contact Restful API to receive the contact information from the Angular client and email it to the admin. Create a routes folder in the server and then create a new file contact.js in it. Add the following code in it: 
JS
  1. We created this file in the routes folder because in Express.js routing is the way how application endpoints or URI (RESTful API addresses)respond to the client’s requests. You can see we have one POST request with the /contact route path and the next statement is a function that has req and res parameters. This function is called the route method and it is derived from HTTP methods. It has a request object that is actually the contact object we are sending from an Angular client application in POST request’s body. Please go to Angular DataService class and see how we are creating an POST request. Next, we are calling a sendContactEmail method and passing contact object values as parameters. The last parameter is a callback function that we are sending as a parameter named callback. When nodemailer sends an email, it returns the response in error and info variables that we can use to determine the success or failure response. We are checking here if there is an error, send an error message to the user otherwise send a thank you message. (You should send a custom error message to the user too, I am just sending error as it is to explain it)
  2. Read more about Express Routing.
  3. Next, let’s add our entry point or main javascript file. Create a new file in a server folder named mazharnco.js and add the following code:  
JS
  1. So here you would see all packages in action that we installed earlier. Let’s briefly understand the code.
    1. In the first five lines, we are creating the module objects of Express.jsPathBody ParserCORS and our own created Contact route. We already learned about each package in previous steps.
    2. Next line var app = express() is important, the app usually represents the Express application that we are creating from express() function of the express module. The app object has different methods e.g.
      1. routing HTTP requests (GET, POST, PUT, DELETE, etc.).
      2. Configuring middleware: Middleware function has reqres objects and next() function to move to next middleware, more like you can interrupt any function, add functionality and move to the rest of the implementation. 
      3. Rendering HTML views
      4. Registering template engine: Like we are going to use Ejs to render our HTML.
    3. Express.js has a very important concept called middleware, so let’s learn about it before moving further: 
      1. Middleware functions have access to RequestResponse objects and next() function in request-response cycle. Through middleware, you can change the request e.g. any validation and also can update the response object before sending it to the client. There can be many middleware functions in one method and we use next() the function to jump to the next one. So in simple words, just consider middleware function sitting between request and response and can do anything before going to request or sending the response back to the requestor.
    4. In the next statement app.engine('html', require('ejs').renderFile);, we are mapping the Ejs template engine to HTML files since we are writing code in Angular when it would be built, it would spit out HTML. The ejs template engine is good for that HTML rendering. 
    5. In app.use(express.static(path.join(__dirname, './views')));, we are using app.use that mounts the middleware function and basically told to take the static files from views folder. We would put Angular build (created by ng build --prod command) in the views folder. The Angular build will have one index.html file, when we would request, http://……../index.html, its path would be matched and index.html static file would be returned by this statement.
    6. Next two statements app.use(express.staticapp.use(bodyParser.urlencoded({ extended: false })); and app.use(bodyParser.json()); are also with app.use that again mounts middleware to enable us to read the request body. Go to routes -> contact‘s POST function, you can see we are using req.body.namereq.body.EmailAddress etc. these statements are not possible without using bodyParser
    7. The app.use(cors()); is making it possible to call the APIs from a different domain. You can explore it more to implement specific rules according to your application (security) requirements.
    8. In app.use("/api", contacts);, we are actually mounting middleware on contacts APIs. E.g. go to contact.js and check the POST call, our path is ‘/contact’. This middleware is simply appending “/api” path to this POST call path. So final path to the contact POST API call would be http://………/api/contact
    9. In the next statement app.get(‘*’….), we are telling our application if the user tries to access an unknown page, just redirect it to the index.html page from views folder.
    10. In the next statement, we are getting the port from the environment file.
    11. The app.listen would open the connection and start listening to the request on the specified port.
  2. In the end, let’s create environment file we keep talking from starting of this article, create new file environment.json in the server folder and add following code in it:  
JS
  1. just go through the above file, we are specifying the application name and entry script mazharnco.js that is our main/entry javascript file. We have two JSON objects with the same variables name but different values. 
  2. Go to the Angular project by running the command in the TERMINALcd mazharncoweb and then build it by ng build --prod command.
  3. It will take a few seconds and finally you would see the dist folder in mazharncoweb, copy its content and go to the server folder. Create a folder views in there and paste the copied content in it.
  4. Since we are using pm2 as our process manager and to run Node.js application, In TERMINAL, run the command: pm2 start environment.json
  5. Now, go to the browser and open the URL: http://localhost:3000 because in our environment.json file, we specified 3000 port for development. Check PM2 Github page for all commands. 

Yaseer Mumtaz

Leave a Reply

Your email address will not be published. Required fields are marked *