Store user information with Angular 6, Nodejs and Express.

Store user information with Angular 6, Nodejs and Express.

Let’s create a very simple Angular form application that stores user information locally in memory on a server.

Let’s create a very simple Angular form application that stores user information locally in memory on a server.

On submitting the form, we’ll populate the data on the next page and add two additional elements to display the guid and customer uid.

The Portfolio API - Grow your coding career effortlessly | gitconnected

Getting Started

First we’ll need Node & NPM installed.

To check if you have node installed run this command in your terminal:

node -v

To confirm that you have npm installed you can run this command:

**npm -v**

If not, you can download & install NodeJS & NPM from https://nodejs.org/en/

Install the Angular CLI:

npm install -g @angular/cli

Generate a new Angular project:

ng new charts6

Navigate to http://localhost:4200/. At this point the application will automatically reload if you change any of the source files. The initial page should be the default Angular 6 page:

The main Application component will have a UI Router that initially shows the Input User Data Form component. On submitting the form**, Application** component will show the Display User Data component.

The Flow

Create components with ng cli

ng new angular-node-express
cd angular-node-express
ng generate component input-user-data-form --spec false

The CLI will create all the appropriate files and place them into the app folder

It should also add declarations into the app.module.ts

Next, we’ll add bootstrap 3 CSS library into the project to add styling.

npm install --save [email protected]

Afterwards add a path to “styles” array in the angular.json

"styles": [
              "node_modules/bootstrap/dist/css/bootstrap.min.css",
              "src/styles.css"
          ]

The Bootstrap grid system uses containers that hold rows and column. Rows and columns are percentage based. It is the container that changes responsively.

The container is used as a wrapper for the content.

We’ll choose a fluid container whose width will always be the width of the device.

fluid-container.html

<div class="container-fluid">

A grid row acts like a wrapper around the columns.

A row is created by adding the class row to an element inside the container.

fluid-container-row.html

<div class="container-fluid">
 <div class="row"></div>
</div>

Ideally, the number of columns equals 12 for every row. Different column class prefixes are used for different sized devices. Here 1 column takes up the size of 12 columns.

Change the app.component.html into the following:

app.component.html

<div class="container-fluid">
  <div class="row">
    <div class="col-xs-12">
      <h1>Hello World!</h1>
    </div>
  </div>
</div>
Running the application in DEV mode

Angular CLI uses webpack underneath to run the application on port 4200.

We’ll run our Node.js API endpoint on port 3000. But making an API call to another server (from port 4200) causes the CORS browser exception.

This is why we’ll use a proxy as a workround to the same-origin policy. The Proxy will re-route our API calls to a Node.js server to avoid the CORS exceptions. CORS is a browser security issue and does not apply to “backend to backend” communication.

All requests made to /api/... from within our application will be forwarded to [http://localhost:3000/api/...](http://localhost:3000/api/....)

With the proxy, our application diagram will look like this:

Create the proxy.conf.json in root folder

proxy.conf.json

{
  "/api/*": {
    "target": "http://localhost:3000",
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  }
}

When starting Angular & Proxy servers use the following command:

ng serve --proxy-config proxy.conf.json
Creating the Input User Data Component

First let's focus on creating UI and work on API endpoints thereafter

There are 3 rules you must follow when making a Bootstrap form:

  1. Every field must be wrapped in a div element
  2. Every should have .control-label class and its for value must match the corresponding <input>’s id, so when the label is clicked, the input becomes focused.
  3. Every should be given .form-control

Set the input-user-data-form.component.html to the following:

input-user-data-form.component.html

	<form>
	<div class="form-group"> <!-- First Name -->
		<label for="first_name" class="control-label">First Name</label>
		<input type="text" class="form-control" id="first_name" name="first_name" placeholder="Martin">
	</div>

	<div class="form-group"> <!-- Last Name -->
		<label for="last_name" class="control-label">Last Name</label>
		<input type="text" class="form-control" id="last_name" name="last_name" placeholder="Toha">
	</div>

	<div class="form-group"> <!-- Email -->
		<label for="email" class="control-label">E-mail</label>
		<input type="text" class="form-control" id="email" name="email" placeholder="[email protected]">
	</div>
							
	<div class="form-group"> <!-- Zip Code-->
		<label for="zipcode" class="control-label">Zip Code</label>
		<input type="text" class="form-control" id="zipcode" name="zipcode" placeholder="#####">
	</div>
	
	<div class="form-group"> <!-- Password -->
		<label for="password" class="control-label">Password</label>
		<input type="text" class="form-control" id="password" name="password" placeholder="*****">
	</div>
	
	<div class="form-group"> <!-- Register Button -->
		<button type="submit" class="btn btn-primary">Register</button>
	</div>

</form>

Change selector in the input-user-data-form.component.ts to input-user-data-form

And add it to app.component.html

Field Validation with Bootstrap

We are going to have to validate our fields prior to submitting the form to the backend. If a field is invalid, we can communicate it to the user by making the entire field red.

For each of the fields, we will:

Add the class .has-error to the .form-groupdiv

And create a <p>with the class .has-textto explain the problem

input-user-data-form.component-validation.html

<form>
	<div class="form-group has-error"> <!-- First Name -->
		<label for="first_name" class="control-label">First Name</label>
		<input type="text" class="form-control" id="first_name" name="first_name" placeholder="Martin">
		<p id="first_name_error" class="help-block">Invalid first name.</p>
	</div>

	<div class="form-group has-error"> <!-- Last Name -->
		<label for="last_name" class="control-label">Last Name</label>
		<input type="text" class="form-control" id="last_name" name="last_name" placeholder="Toha">
		<p id="last_name_error" class="help-block">Invalid last name.</p>
	</div>

	<div class="form-group has-error"> <!-- Email -->
		<label for="email" class="control-label">E-mail</label>
		<input type="text" class="form-control" id="email" name="email" placeholder="[email protected]">
		<p id="email_error" class="help-block">Invalid email address.</p>
	</div>
							
	<div class="form-group has-error"> <!-- Zip Code -->
		<label for="zipcode" class="control-label">Zip Code</label>
		<input type="text" class="form-control" id="zipcode" name="zipcode" placeholder="#####">
		<p id="zipcode_error" class="help-block">Invalid zip code.</p>
	</div>

	<div class="form-group has-error"> <!-- Password -->
		<label for="password" class="control-label">Password</label>
		<input type="text" class="form-control" id="password" name="password" placeholder="*****">
		<p id="password_error" class="help-block">Invalid password.</p>
	</div>
	
	<div class="form-group has-error"> <!-- Register Button -->
		<button type="submit" class="btn btn-primary">Register</button>
	</div>

</form>

Here is the form with errors added for every field:

Making a Reactive Form

A reactive form is a bit different from template-driven forms by providing more predictability with synchronous access to the data model, immutability with observable operators, and change tracking through observable streams.

To use the reactive form, we must import the FormsModule & ReactiveFormsModule from the @angular/forms package and add it to our app.module.ts

Next, lets modify the input-user-data-form.component.

We’ll inject the formBuilder into the component for use in the ngOnInit life cycle method. FormBuilder a service that helps making forms easier.

The FormBuilder will create a FormGroup userForm with FormControls. Each FormControl has a default value and a set of Validators.

Think of the userForm as a schema for the actual values. It holds validation rules for fields inside the form.

We’ll add registered & submitted boolean flags to the Component. We’ll use these to indicate the current form state**.**

Also, we’ll create a validator function for every input, see invalidFirstName(), invalidLastName(), invalidEmail(), invalidZipcode(), invalidPassword().

A validator function will be used in markup to hide / show error messages for each field.

input-user-data-form.components.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'input-user-data-form',
  templateUrl: './input-user-data-form.component.html',
  styleUrls: ['./input-user-data-form.component.css']
})

export class InputUserDataFormComponent implements OnInit {
	registered = false;
	submitted = false;
	userForm: FormGroup;

  constructor(private formBuilder: FormBuilder)
  {

  }

  invalidFirstName()
  {
  	return (this.submitted && this.userForm.controls.first_name.errors != null);
  }

  invalidLastName()
  {
  	return (this.submitted && this.userForm.controls.last_name.errors != null);
  }

  invalidEmail()
  {
  	return (this.submitted && this.userForm.controls.email.errors != null);
  }

  invalidZipcode()
  {
  	return (this.submitted && this.userForm.controls.zipcode.errors != null);
  }

  invalidPassword()
  {
  	return (this.submitted && this.userForm.controls.password.errors != null);
  }

  ngOnInit()
  {
  	this.userForm = this.formBuilder.group({
  		first_name: ['', Validators.required],
  		last_name: ['', Validators.required],
  		email: ['', [Validators.required, Validators.email]],
  		zipcode: ['', [Validators.required, Validators.pattern('^[0-9]{5}(?:-[0-9]{4})?$')]],
  		password: ['', [Validators.required, Validators.minLength(5), Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')]],
  	});
  }

  onSubmit()
  {
  	this.submitted = true;

  	if(this.userForm.invalid == true)
  	{
  		return;
  	}
  	else
  	{
  		this.registered = true;
  	}
  }

};

In the input-user-data-form.component.html, and for every Reactive form we’ll use a directive [formGroup] to bind to userForm variable we defined in the component

We’ll bind the onSubmit handler via the (ngSubmit) directive.

To connect an HTML input element to a Reactive form we need to add formControlNameattribute to each of the form inputs.

We’ll use the *ngIf & [ngClass] directives to control error messages. The styles and validation markup will get displayed after user attempts to submit the form. This is controlled with [submitted] property of the component.

After submitting the form, it will be validated every time user changes the input value, causing errors to show & hide dynamically.

input-user-data-form.component-02.html

<form [formGroup]="userForm" (ngSubmit)="onSubmit()">

	<div class="form-group" [ngClass]="{ 'has-error': invalidFirstName() }"> <!-- First Name -->
		<label for="first_name" class="control-label">First Name</label>
		<input type="text" formControlName="first_name" class="form-control" id="first_name" name="first_name" placeholder="Martin">
		<p *ngIf="invalidFirstName()" id="first_name_error" class="help-block">Invalid first name.</p>
	</div>

	<div class="form-group" [ngClass]="{ 'has-error': invalidLastName() }"> <!-- Last Name -->
		<label for="last_name" class="control-label">Last Name</label>
		<input type="text" formControlName="last_name" class="form-control" id="last_name" name="last_name" placeholder="Toha">
		<p *ngIf="invalidLastName()" id="last_name_error" class="help-block">Invalid last name.</p>
	</div>

	<div class="form-group" [ngClass]="{ 'has-error': invalidEmail() }"> <!-- Email -->
		<label for="email" class="control-label">E-mail</label>
		<input type="text" formControlName="email" class="form-control" id="email" name="email" placeholder="[email protected]">
		<p *ngIf="invalidEmail()" id="email_error" class="help-block">Invalid email address.</p>
	</div>

	<div class="form-group" [ngClass]="{ 'has-error': invalidZipcode() }"> <!-- Zip Code-->
		<label for="zipcode" class="control-label">Zip Code</label>
		<input type="text" formControlName="zipcode" class="form-control" id="zipcode" name="zipcode" placeholder="#####">
		<p *ngIf="invalidZipcode()" id="zipcode_error" class="help-block">Invalid zip code.</p>
	</div>

	<div class="form-group" [ngClass]="{ 'has-error': invalidPassword() }"> <!-- Password -->
		<label for="password" class="control-label">Password</label>
		<input type="password" formControlName="password" class="form-control" id="password" name="password" placeholder="*****">
		<p *ngIf="invalidPassword()" id="password_error" class="help-block">Invalid password.</p>
	</div>
	
	<div class="form-group has-error"> <!-- Register Button -->
		<button type="submit" class="btn btn-primary">Register</button>
	</div>

</form>

Here is what the form looks like initially:

And the form after filling out some fields with error:

Looks good so far! Lets continue with the next component.

Creating the Display User Data Component

The next Angular component will display user data. This will be a simple component that visualizes a data model passed into it.

Lets create a data model UserInfoModel in app/models, we’ll make it deserialize an object when its passed into the constructor.

UserInfoModel.ts

export class UserInfoModel
{
	guid: string;
	customerUid: string;
	
	first_name: string;
	last_name: string;

	email: string;
	zipcode: string;

	password: string;

	constructor(obj: any = null)
	{
		if(obj != null)
		{
			Object.assign(this, obj);
		}
	}
}

The view display-user-data.component.html binds to the model via interpolation {{…}} and displays the information.

display-user-data.component.html

<legend>User Information</legend>
<div>
	<div class="form-group row"> <!-- GUD -->
		<label class="col-xs-6 col-form-label">GUID</label>
		<div class="col-xs-6">{{user.guid}}</div>
	</div>

	<div class="form-group row"> <!-- Customer UID -->
		<label class="col-xs-6 col-form-label">Customer UID</label>
		<div class="col-xs-6">{{user.customerUid}}</div>
	</div>

	<div class="form-group row"> <!-- First Name -->
		<label class="col-xs-6 col-form-label">First Name</label>
		<div class="col-xs-6">{{user.first_name}}</div>
	</div>

	<div class="form-group row"> <!-- Last Name -->
		<label class="col-xs-6 col-form-label">Last Name</label>
		<div class="col-xs-6">{{user.last_name}}</div>
	</div>

	<div class="form-group row"> <!-- E-mail -->
		<label class="col-xs-6 col-form-label">E-mail</label>
		<div class="col-xs-6">{{user.email}}</div>
	</div>

	<div class="form-group row"> <!-- Zip Code -->
		<label class="col-xs-6 col-form-label">Zip Code</label>
		<div class="col-xs-6">{{user.zipcode}}</div>
	</div>

	<div class="form-group row"> <!-- Password -->
		<label class="col-xs-6 col-form-label">Password</label>
		<div class="col-xs-6">{{user.password}}</div>
	</div>

</div>

And just for testing purposes, DisplayUserDataComponent class will assign some default values into the UserInfoModel

display-user-data.component.ts

import { Component, OnInit } from '@angular/core';
import {UserInfoModel} from '../models/userInfo'

@Component({
  selector: 'display-user-data',
  templateUrl: './display-user-data.component.html',
  styleUrls: ['./display-user-data.component.css']
})

export class DisplayUserDataComponent implements OnInit {
	
	user: UserInfoModel = new UserInfoModel({guid: "D21ds12x", 
		customerUid: "cust2dsa12dsa", 
		first_name: "John", 
		last_name: "Doe", 
		email: "[email protected]", 
		zipcode: 10283,
		password: "Idasn2x2#"});

	constructor() { }

	ngOnInit()
	{

	}

}


Both of the pages look great!

Now, lets connect the Router into the AppComponent to establish a page flow

Connecting Routes & RouterModule

Our goal with routing is to have the InputUserDataFormComponentrendered when the url is /, and DisplayUserDataComponentshown when the url is /user/:uid

First, lets setup the imports to @angular/router, then define an array routes of our paths and destination pages.

const routes: Routes = [
  {
    path: '',
    component: InputUserDataFormComponent
  },
  {
    path: 'user/:uid',
    component: DisplayUserDataComponent
  }
];

In the importsadd RouterModule.forRoot(routes)

app.module-w-routes.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { InputUserDataFormComponent } from './input-user-data-form/input-user-data-form.component';
import { DisplayUserDataComponent } from './display-user-data/display-user-data.component';
import { Routes, RouterModule } from "@angular/router";

const routes: Routes = [
  {
    path: '',
    component: InputUserDataFormComponent
  },
  {
    path: 'user/:uid',
    component: DisplayUserDataComponent
  }
];

@NgModule({
  declarations: [
    AppComponent,
    InputUserDataFormComponent,
    DisplayUserDataComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule.forRoot(routes)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Place the router-outletin the app.component.html

app.component-wroute.html

<div class="container-fluid">
  <div class="row">
    <div class="col-xs-12">
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

Now the initial “/” root page looks like this:

Type “/user/a01” in the address bar and you get the User Information page

All works as intended on the client! Now lets continue with creation of API endpoint.

Creating API endpoint in Node.js & Express

We’ll use the express-generator-api to make a Node.js API quickly by generating a project.

Install express-generator:

npm install -g express-generator-api

Create the API:

express-api angular-node-express-api & cd angular-node-express-api

Install dependencies:

npm install

Тhe file structure generated should be the following:

At this point all the basics of an API have been implemented by the generator.

For example, body parser & cookie parser are part of the app.js. Here express will try identify any JSON data that comes into our application and parse it for us.

Next, we are going to make the following API endpoints.

/customer will insert a new customer and return auto-incremented customer.id

/customer/:uid will retrieve a single customer by customer uid

/generate_guid will generate a tracking_guide that Angular UI will use when creating a new customer

Router /generate_uid

Lets copy users.js to generate_uid.js just to have a basic router. We’ll modify this router to return a random uid

Install uid-safe, which generates a uid safe for cookies

npm install uid-safe

Include it in generate_uid.js

var uid = require('uid-safe')

And return it with the response

generate_uid.js

var express = require('express');
var uid = require('uid-safe');

var router = express.Router();

/* GET a guid. */
router.get('/', function(req, res, next)
{
	var strUid = uid.sync(18);

	res.json({guid: strUid});
});

module.exports = router;

We’ll need to hook up the generate_uid router in the app.js

app.use('/api/v1/generate_uid', generate_uid);

The route returns a JSON with the GUID. Great!

{"guid":"K7VPC3I9kxIJ4Ct2_2ZR7Xb1"}

Router /customer

For every API service I usually have a model for the data and a service that performs all CRUD operations with it; that way there is a level of abstraction between the API request, storage & validation, but also a good way to access the service from anywhere in the application.

In this example, we’ll simply store customer data in memory.

The service will increment a customer UID every time a new customer is created.

We’ll use that customer UID to retrieve the customer data as well.

Create the models directory and add the following model.customer.js in there.

model.customer.js

class CustomerModel
{
	constructor(uid, first_name, last_name, email, zipcode, password)
	{
		this.uid = uid;
		this.first_name = first_name;
		this.last_name = last_name;
		this.email = email;
		this.zipcode = zipcode;
		this.password = password;
	}
}

module.exports = CustomerModel;

Then, create services directory and add a service.customer.js in there.

CustomerService implements all the CRUD operations create, read, update and delete the CustomerModel. It uses the counter to increment the customer uid; and stores all the customers into the customers object.

It’s important to validate our data on the server as well as the client. I usually keep validation as part of the service object, which is either a separate method or part of the CRUD operation.

We’ll implement the validation using the fastest-validator library.

Install fastest-validator library:

npm install fastest-validator --save

Import it in the CustomerService service object and create an instance of the Validator with custom schema.

var validator = require('fastest-validator');

The Schema object contains all validation rules, which is then used by the Validator instance to validate data against it.

Then, we’ll need to notify UI if validation fails on the server. If that happens, the create operation will throw an Error with list of errors for every failed validation.


services\service.customer.js

The list of errors will propagate into the response, which will be handled by Angular to communicate an error.

service.customer.js

const CustomerModel = require("../models/model.customer");
let Validator = require('fastest-validator');


let customers = {};
let counter = 0;

/* create an instance of the validator */
let customerValidator = new Validator();

/* use the same patterns as on the client to validate the request */
let namePattern = /([A-Za-z\-\’])*/;
let zipCodePattern = /^[0-9]{5}(?:-[0-9]{4})?$/;
let passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$/;

/* customer validator shema */
const customerVSchema = {
		guid: {type: "string", min: 3},
		
		first_name: { type: "string", min: 1, max: 50, pattern: namePattern},
		last_name: { type: "string", min: 1, max: 50, pattern: namePattern},
		email: { type: "email", max: 75 },
		zipcode: { type: "string", max: 5, pattern: zipCodePattern},

		password: { type: "string", min: 2, max: 50, pattern: passwordPattern}
	};

/* static customer service class */
class CustomerService
{
	static create(data)
	{
		var vres = customerValidator.validate(data, customerVSchema);
		
		/* validation failed */
		if(!(vres === true))
		{
			let errors = {}, item;

			for(const index in vres)
			{
				item = vres[index];

				errors[item.field] = item.message;
			}
			
			throw {
			    name: "ValidationError",
			    message: errors
			};
		}

		let customer = new CustomerModel(data.first_name, data.last_name, data.email, data.zipcode, data.password);

		customer.uid = 'c' + counter++;

		customers[customer.uid] = customer;

		return customer;
	}

	static retrieve(uid)
	{
		if(customers[uid] != null)
		{
			return customers[uid];
		}
		else
		{
			throw new Error('Unable to retrieve a customer by (uid:'+ uid +')');
		}
	}

	static update(uid, data)
	{
		if(customers[uid] != null)
		{
			const customer = customers[uid];
			
			Object.assign(customer, data);
		}
		else
		{
			throw new Error('Unable to retrieve a customer by (uid:'+ cuid +')');
		}
	}

	static delete(uid)
	{
		if(customers[uid] != null)
		{
			delete customers[uid];
		}
		else
		{
			throw new Error('Unable to retrieve a customer by (uid:'+ cuid +')');
		}
	}
}

module.exports = CustomerService;

Lets connect the CustomerService to express router.

We’ll be using the async / await, which is a better way to write asynchronous code. Previous options are callbacks and promises, in fact async/await is built on top of promises; but async / await make the code behave & read a little more like synchronous code.

In the following router we implement all the CRUD operations using the CustomerService singleton.

Take a look at the create operation, where we submit user data and how errors are propagated into the response via try / catch block. The code is easy to read.


routes-customer.js

var express = require('express');
var router = express.Router();
var CustomerService = require('../services/service.customer');

/* GET customer listing. */
router.get('/', async function(req, res, next)
{
	res.json({error: "Invalid Customer UID."});
});

/* adds a new customer to the list */
router.post('/', async (req, res, next) =>
{
	const body = req.body;

	try
	{
		const customer = await CustomerService.create(body);

		if(body.guid != null)
		{
			customer.guid = body.guid;
		}

		res.cookie('guid', customer.guid, { maxAge: 900000, httpOnly: true });

		// created the customer! 
		return res.status(201).json({ customer: customer });
	}
	catch(err)
	{
		if (err.name === 'ValidationError')
		{
        	return res.status(400).json({ error: err.message });
		}

		// unexpected error
		return next(err);
	}
});

/* retrieves a customer by uid */
router.get('/:id', async (req, res, next) =>
{
	try
	{
		const customer = await CustomerService.retrieve(req.params.id);

		return res.json({ customer: customer });
	}
	catch(err)
	{
		// unexpected error
		return next(err);
	}
});

/* updates the customer by uid */
router.put('/:id', async (req, res, next) =>
{
	try
	{
		const customer = await CustomerService.update(req.params.id, req.body);

		return res.json({ customer: customer });
	}
	catch(err)
	{
		// unexpected error
		return next(err);
	}
});

/* removes the customer from the customer list by uid */
router.delete('/:id', async (req, res, next) =>
{
	try
	{
		const customer = await CustomerService.delete(req.params.id);

		return res.json({success: true});
	}
	catch(err)
	{
		// unexpected error
		return next(err);
	}
});

module.exports = router;

Next, we’ll need to modify the input-user-data-form.component & its template to support showing the server side errors, in case the validation fails on the server.

In the InputUserDataFormComponent we’ll add the serviceErrors object, which will contain all the server side errors for each fields. And add to the validator methods to check if the error message for that field exists, like so:


app\input-user-data-form.component.ts

We’ll also modify the onSubmit method, and add an error handler to our request which will simply set serviceErrors object.


app\input-user-data-form\input-user-data-form.component.ts

Next we’ll add a reference to server side errors in the input-user-data-form.component.html template to display a server side error in case it exists:


app\input-user-data-form\input-user-data-form.component.html

Now, we’ll know if validation fails on the server, since messages are going to be propagated to Angular UI.

Everything looks good, lets connect our routers in the app.js


app-routes.js

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var generate_uid = require('./routes/generate_uid');
var customer = require('./routes/customer');


var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser())

app.use('/api/v1/customer', customer);
app.use('/api/v1/generate_uid', generate_uid);

module.exports = app;

We are almost there!

We are done creating the application, now a couple of minor details.

We are using a proxy in order to go around the CORS browser issue by having the Webpack on port 4200 communicate with Node.js server on port 3000. This is a good solution for the development environment, but we’ll need to have a better implementation when moving to production.

The API server will need to either enable the API for all origins or white list our access point.

For now, lets just enable CORS for all origins

To enable our API for all is easy, just add the following code to app.js

app-cors-enabled.js

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

Uncaught Exceptions

Another minor detail we haven’t covered is handling of Uncaught Exceptions

Because Node.js runs on a single processor uncaught exceptions are an issue to be aware of when developing applications.

When your application throws an uncaught exception you should consider that your application is now running in an unclean state. You can’t reliably continue your program at this point because you don’t really know what got affected by the error.

The best way to handle a crash is to collect as much data about it, send the errors to an external crash service or log it; and restart the server.

For our simple application, we’ll implement the appropriate functions, just place these in the beginning of your app.js

I’ll keep the reporter method empty, which we will connect in a later article to an external crash service

app-uncaught.js

let reporter = function (type, ...rest)
{
	// remote reporter logic goes here
};

/* handle an uncaught exception & exit the process */
process.on('uncaughtException', function (err)
{
	console.error((new Date).toUTCString() + ' uncaughtException:', err.message);
	console.error(err.stack);

	reporter("uncaughtException", (new Date).toUTCString(), err.message, err.stack);

	process.exit(1);
});

/* handle an unhandled promise rejection */
process.on('unhandledRejection', function (reason, promise)
{
	console.error('unhandled rejection:', reason.message || reason);

	reporter("uncaughtException", (new Date).toUTCString(), reason.message || reason);
})

Finally! To start the API server:

npm start

Try hitting the http://localhost:3000/api/v1/generate_uid

or http://localhost:3000/api/v1/customer

And you should see some JSON data.

Integrating services into the Angular application

To quickly integrate the Angular application we are going to:

Import & Inject HttpClient & Router into the InputUserDataFormComponent

Next, we’ll retrieve the GUID from the ‘/api/v1/generate_uid’ API service in the constructor of the InputUserDataFormComponent and set the guid variable


constructor of InputUserDataFormComponent

In the onSubmit method of the InputUserDataFormComponent we’ll post the data into the ‘/api/v1/customer’ service & navigate the Angular Router to the next page /user/:id

The full source code:

input-user-data-form.component-wroute-api.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
import { HttpClient } from "@angular/common/http";
import { Router } from "@angular/router";

@Component({
  selector: 'input-user-data-form',
  templateUrl: './input-user-data-form.component.html',
  styleUrls: ['./input-user-data-form.component.css']
})

export class InputUserDataFormComponent implements OnInit {
	registered = false;
	submitted = false;
	userForm: FormGroup;
	guid: string;
	serviceErrors:any = {};

  constructor(private formBuilder: FormBuilder, private http: HttpClient, private router: Router)
  {
  	this.http.get('/api/v1/generate_uid').subscribe((data:any) => {
      this.guid = data.guid;
    }, error => {
        console.log("There was an error generating the proper GUID on the server", error);
    });
  }

  invalidFirstName()
  {
  	return (this.submitted && (this.serviceErrors.first_name != null || this.userForm.controls.first_name.errors != null));
  }

  invalidLastName()
  {
  	return (this.submitted && (this.serviceErrors.last_name != null || this.userForm.controls.last_name.errors != null));
  }

  invalidEmail()
  {
  	return (this.submitted && (this.serviceErrors.email != null || this.userForm.controls.email.errors != null));
  }

  invalidZipcode()
  {
  	return (this.submitted && (this.serviceErrors.zipcode != null || this.userForm.controls.zipcode.errors != null));
  }

  invalidPassword()
  {
  	return (this.submitted && (this.serviceErrors.password != null || this.userForm.controls.password.errors != null));
  }

  ngOnInit()
  {
  	this.userForm = this.formBuilder.group({
  		first_name: ['', [Validators.required, Validators.maxLength(50)]],
  		last_name: ['', [Validators.required, Validators.maxLength(50)]],
  		email: ['', [Validators.required, Validators.email, Validators.maxLength(75)]],
  		zipcode: ['', [Validators.required, Validators.pattern('^[0-9]{5}(?:-[0-9]{4})?$')]],
  		password: ['', [Validators.required, Validators.minLength(5), Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')]],
  	});
  }

  onSubmit()
  {
  	this.submitted = true;

  	if(this.userForm.invalid == true)
  	{
  		return;
  	}
  	else
  	{
  		let data: any = Object.assign({guid: this.guid}, this.userForm.value);

  		this.http.post('/api/v1/customer', data).subscribe((data:any) => {
	      
	      let path = '/user/' + data.customer.uid;

	      this.router.navigate([path]);
	    }, error =>
	    {
	    	this.serviceErrors = error.error.error;
        });

  		this.registered = true;

  	}
  }

};

Then lets Import & Inject HttpClient & ActivatedRoute into the DisplayUserDataComponent

Retrieve customer data from the ‘/api/v1/customer/:id’ API and populate the UserInfoModel with new data, and have DisplayUserDataComponent view redraw itself with new data via interpolation {{…}}

display-user-data.component-wroute-api.ts

import { Component, OnInit } from '@angular/core';
import {UserInfoModel} from '../models/userInfo';
import { HttpClient } from "@angular/common/http";
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'display-user-data',
  templateUrl: './display-user-data.component.html',
  styleUrls: ['./display-user-data.component.css']
})

export class DisplayUserDataComponent implements OnInit
{

	user: UserInfoModel = new UserInfoModel({guid: "D21ds12x", 
		uid: "cust2dsa12dsa", 
		first_name: "John", 
		last_name: "Doe", 
		email: "[email protected]", 
		zipcode: 10283,
		password: "Idasn2x2#"});

	constructor(private http: HttpClient, private route: ActivatedRoute) {

	}

	private subscriber: any;

	ngOnInit()
	{
		this.subscriber = this.route.params.subscribe(params => {
	       
	       this.http.get('/api/v1/customer/' + params.uid).subscribe((data:any) => {

				this.user = new UserInfoModel(data.customer);
		    });
	    });
	}

}

The initial page of the application ‘/’:

Fill in the form and press Register:

Next page, the user information is displayed.

After creating a customer, you can also type in the customer url followed by customer uid to retrieve customer data:

http://localhost:3000/api/v1/customer/c0

{"customer":{"first_name":"John","last_name":"Doe","email":"[email protected]","zipcode":"12345","password":"Udsakln12dsa","uid":"c0","guid":"gCnqJdp3saMNPpJfXPj6DORy"}}

Source Code is accessible at Github bellow:

Angular UI:
https://github.com/jsmuster/angular-node-express

Node.js + Express API:
https://github.com/jsmuster/angular-node-express-api

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step) - Learn the basics of Node.js. This Node.js tutorial will guide you step by step so that you will learn basics and theory of every part. Learn to use Node.js like a professional. You’ll learn: Basic Of Node, Modules, NPM In Node, Event, Email, Uploading File, Advance Of Node.

Node.js for Beginners

Learn Node.js from Scratch (Step by Step)

Welcome to my course "Node.js for Beginners - Learn Node.js from Scratch". This course will guide you step by step so that you will learn basics and theory of every part. This course contain hands on example so that you can understand coding in Node.js better. If you have no previous knowledge or experience in Node.js, you will like that the course begins with Node.js basics. otherwise if you have few experience in programming in Node.js, this course can help you learn some new information . This course contain hands on practical examples without neglecting theory and basics. Learn to use Node.js like a professional. This comprehensive course will allow to work on the real world as an expert!
What you’ll learn:

  • Basic Of Node
  • Modules
  • NPM In Node
  • Event
  • Email
  • Uploading File
  • Advance Of Node

Single Page Application with Angular.js Node.js and CouchDB

Single Page Application with Angular.js Node.js and CouchDB

We posted the article on Single Page Application with Angular.js, Node.js and CouchDB with Express

We posted the article on Single Page Application with Angular.js, Node.js and CouchDB Cradle Module with Express 3. Current post is a way to migrate the same with Express 4.

This article describes a way to make a web application with Javascript based Web Server with CouchDB with Angular.js and Node.js.

Here we have selected

  • Angular.js for client side development – Single Page Application
  • Cross Domain Communication in between Angular.js and Node.js
  • Node.js for server side development
  • Rest based web service creation with express.js (Express 4)
  • Database – CouchDb
  • Node.js Cradle Module Extention (to make communication with CouchDB)
  • Making CouchDB views with Map-Reduce to fetch the data

We have created a Proof of Concept with Javascript based web server, where we have focused on dealing with NoSql (CouchDB) with javascript based framework Node.js and angular.js on client side.

Architecture at a glance



Steps

Installation

  • Download and install Node.js from here.
  • To Develop the application we need to install cradle module for Node.js
  • Command – **npm install cradle **(should be connected to internet)
  • We need to install express.js for node.jsCommand – npm install express (should be connected to internet)

Configuration Code

Now we will try to describe the code portion

var application_root = __dirname,
express = require("express"),
path = require("path");

Here we have initialised the express.js within javascript variables in respect of Node.js concept.

var databaseUrl = "sampledb";
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://admin:[email protected]', 5984, {
auth: { username: 'admin', password: 'admin' }
});
var db = connection.database(databaseUrl);

Here we have initialised the express web server in app variable.

var databaseUrl = "sampledb";
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://admin:[email protected]', 5984, {
auth: { username: 'admin', password: 'admin' }
});
var db = connection.database(databaseUrl);

Here we have made the connection to the couchdb database using the Node.js cradle module extension library.

// Config
var env = process.env.NODE_ENV || 'development';
if ('development' == env) {
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var methodOverride = require('method-override');
app.use(methodOverride());
app.use(express.static(path.join(application_root, "public")));
var errorhandler = require('errorhandler');
app.use(errorhandler());
}

Here we have made the configuration related to express.js which is very much different from Express 3.

In Express 3 the same portion was written as

      app.configure(function () {
         app.use(express.bodyParser());
         app.use(express.methodOverride());
         app.use(app.router);
         app.use(express.static(path.join(application_root, "public")));
         app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
      });

This makes a little sense how the Express 3 is migrated to Express 4.

In Express 4 app.use(app.router); is removed. Instead it is added with the Rest services.The way of configuration is also changed as well as the changes reflected in use of bodyParser() ,methodOverride() ,methodOverride() ,errorHandler({…}).

Rest Services Code

app.route('/api').get(function (req, res) {
   res.header("Access-Control-Allow-Origin", "http://localhost");
   res.send('Express API is running');
});

Here we have made our first REST based web service and tested whether the express.js is running.Our sample api will be http://127.0.0.1:1212/api or http://localhost:1212/api

app.route('/getangularusers').get(function (req, res) {
 res.header("Access-Control-Allow-Origin", "http://localhost");
 res.header("Access-Control-Allow-Methods", "GET, POST");
 res.writeHead(200, {'Content-Type': 'application/json'});
 str='[';
 db.view('characters/all', function (err, response) {
    response.forEach(function (row) {
            //console.log("%s is on the %s side of the force.", row.name, row.force);
        str = str + '{ "name" : "' + row.username + '"},' +'\n';
        });
        str = str.trim();
        str = str.substring(0,str.length-1);
    str = str + ']';
    res.end( str);
 });
});

Here we have created another REST api to get all username from user collection and so we have done the cradle query.


CouchDB View Creation

This view creation is to be executed, before running the Angular Client Application to get specific set of data from couchdb.

To run this view creation, we should put

[httpd]  
authentication_handlers = {couch_httpd_auth, null_authentication_handler}  

in the local.ini file of <>/etc/couchdb folder to execute this map function without being the admin user.

So the REST api of view creation is

app.route('/createview').get(function (req, res) { // Before running the Angular Application, the view must be created
 db.save('_design/characters', { // Main View Family Name
        all: { // A particular set of data selection by javascript map-reduce
        map: function (doc) {
           if (doc.username) emit(doc.username, doc); // specific code to execute map function on each document
       }
     }
   });
});

and the sample api will be – http://127.0.0.1:1212/getangularusers (Get Method).

Next we have made a POST request to create an user via REST calling.

app.route('/insertangularcouchuser').post(function (req, res){
console.log("POST: ");
res.header("Access-Control-Allow-Origin", "http://localhost");
res.header("Access-Control-Allow-Methods", "GET, POST");
// The above 2 lines are required for Cross Domain Communication(Allowing the methods that come as Cross
// Domain Request
console.log(req.body);
console.log(req.body.mydata);
var jsonData = JSON.parse(req.body.mydata);
var doc = {email: jsonData.email, password: jsonData.password, username: jsonData.username};
db.save('\''+Math.random()+'\'', doc, function (err, res) {
   if (err) {
       // Handle error
       res += ' SAVE ERROR: Could not save record!!\n';
       } else {
       // Handle success
       res += ' SUCESSFUL SAVE\n';
       }
   });
});

Our sample api will be – http://127.0.0.1:1212/insertangularcouchuser (Post Method – accessed by client side)

// Launch server
app.listen(1212);

We have made the server to listen at 1212 port.

Now run node appcouchdbangular.js from command shell. This is our node.js specific code file.

For references :


Angular.js part

Below is the code in Angular Controller

'use strict';

var myApp = angular.module('myApp', []); // <strong>Taking Angular Application in Javascript Variable</strong>

// <strong>Below is the code to allow cross domain request from web server through angular.js</strong>
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);

/* Controllers */

function UserListCtrl($scope, $http, $templateCache) {

var method = 'POST';
var inserturl = 'http://localhost:1212/insertangularcouchuser';// <strong>URL where the Node.js server is running</strong>
$scope.codeStatus = "";
$scope.save = function() {
//<strong> Preparing the Json Data from the Angular Model to send in the Server.</strong>
var formData = {
'username' : this.username,
'password' : this.password,
'email' : this.email
};

this.username = '';
this.password = '';
this.email = '';

var jdata = 'mydata='+JSON.stringify(formData); // &lt;strong&gt;The data is to be string.&lt;/strong&gt;

$http({ &lt;strong&gt;// Accessing the Angular $http Service to send data via REST Communication to Node Server.&lt;/strong&gt;
        method: method,
        url: inserturl,
        data:  jdata ,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        cache: $templateCache
    }).
    success(function(response) {
    console.log("success"); &lt;strong&gt;// Getting Success Response in Callback&lt;/strong&gt;
            $scope.codeStatus = response.data;
    console.log($scope.codeStatus);

    }).
    error(function(response) {
    console.log("error"); &lt;strong&gt;// Getting Error Response in Callback&lt;/strong&gt;
            $scope.codeStatus = response || "Request failed";
    console.log($scope.codeStatus);
    });
$scope.list();&lt;strong&gt;// Calling the list function in Angular Controller to show all current data in HTML&lt;/strong&gt;
    return false;

};

$scope.list = function() {
var url = 'http://localhost:1212/getangularusers';// <strong>URL where the Node.js server is running</strong>
$http.get(url).success(function(data) {
$scope.users = data;
});
<strong>// Accessing the Angular $http Service to get data via REST Communication from Node Server </strong>
};

$scope.list();
}

Angular Template and HTML

       <html lang="en" ng-app="myApp">
.....

We have referred the Angular Application in above code

   <body ng-controller="UserListCtrl">
.....

We have referred the Angular Controller in above code

   Search: <input ng-model="user">
<div class="span10">
<!--Body content-->
<ul class="users">
<li ng-repeat="user in users | filter:user ">
{{user.name}}
</li>
</ul>
</div>

We have used the ng-repeat tag to take the users data model from REST communication and shown in HTML

   <form name="myform" id="myform1" ng-submit="save()">
<fieldset>
<legend>New User</legend>
<div class="control-group">
<center>
<input type="text" placeholder="User…" ng-model="username" size=50 required/>
</center>
<center>
<input type="text" placeholder="Password…" ng-model="password" size=50 required/>
</center>
<center>
<input type="text" placeholder="Email…" ng-model="email" size=50 required/>
</center>
</div>
</fieldset>
<p>
<div><center><button type="submit" >Save now...</button></center></div>
</p>
</form>

We have used the ng-submit tag to send the user data model from REST communication and sent to node server to save in CouchDB.

Reader can download the complete source-code in GitHub.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Learn More

The Complete Node.js Developer Course (3rd Edition)

Angular & NodeJS - The MEAN Stack Guide

NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

Node.js: The Complete Guide to Build RESTful APIs (2018)

Angular 7 (formerly Angular 2) - The Complete Guide

Angular & NodeJS - The MEAN Stack Guide

The Web Developer Bootcamp

MEAN Stack Tutorial MongoDB, ExpressJS, AngularJS and NodeJS

Angular 7 CRUD With Node.JS API

Angular and Nodejs Integration Tutorial

Angular + WebSocket + Node.js Express = RxJS WebSocketSubject ❤️

Setting up your new Mac for MEAN Stack development

Front-end Developer Handbook 2019

Originally published on https://codequs.com

Hetu Rajgor's answer to What are the major differences between Java, AngularJS, and JavaScript and Node JS? - Quora

<img src="https://moriohcdn.b-cdn.net/70b437cf37.png">Java is a programming language which is owned by Oracle. More than 3 Million devices are running in Java.&nbsp;JS is a client-side programming language used for creating dynamic websites and apps to run in the client's browser.

Java is a programming language which is owned by Oracle. More than 3 Million devices are running in Java. JS is a client-side programming language used for creating dynamic websites and apps to run in the client's browser.