Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon

Build user directory app with Angular [Tutorial]

Save for later
  • 12 min read
  • 05 Jul 2018

article-image

In this article, we will learn how to build a user directory with Angular. The app will have a REST API which will be created during the course of this example. In this simple example, we'll be creating a users app which will be a table with a list of users together with their email addresses and phone numbers.

Each user in the table will have an active state whose value is a boolean. We will be able to change the active state of a particular user from false to true and vice versa. The app will give us the ability to add new users and also delete users from the table.

diskDB will be used as the database for this example. We will have an Angular service which contains methods that will be responsible for communicating with the REST end points. These methods will be responsible for making get, post, put, and delete requests to the REST API.

The first method in the service will be responsible for making a get request to the API. This will enable us to retrieve all the users from the back end. Next, we will have another method that makes a post request to the API. This will enable us to add new users to the array of existing users.

The next method we shall have will be responsible for making a delete request to the API in order to enable the deletion of a user. Finally, we shall have a method that makes a put request to the API. This will be the method that gives us the ability to edit/modify the state of a user.

In order to make these requests to the REST API, we will have to make use of the HttpModule. The aim of this section is to solidify your knowledge of HTTP. As a JavaScript and, in fact, an Angular developer, you are bound to make interactions with APIs and web servers almost all the time. So much data used by developers today is in form of APIs and in order to make interactions with these APIs, we need to constantly make use of HTTP requests. As a matter of fact, HTTP is the foundation of data communication for the web.

This article is an excerpt from the book, TypeScript 2.x for Angular Developers, written by Chris Nwamba.

Create a new Angular app


To start a new Angular app, run the following command:

ng new user


This creates the Angular 2 user app.

Install the following dependencies:

  • Express
  • Body-parser
  • Cors

npm install express body-parser cors --save

Create a Node server


Create a file called server.js at the root of the project directory. This will be our node server.

Populate server.js with the following block of code:

// Require dependencies
const express = require('express');
const path = require('path');
const http = require('http');
const cors = require('cors');
const bodyParser = require('body-parser');
// Get our API routes
const route = require('./route');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Use CORS
app.use(cors());
// Set our api routes
app.use('/api', route);
/**
* Get port from environment.
*/
const port = process.env.PORT || '3000';
/**
* Create HTTP server.
*/
const server = http.createServer(app);
//Listen on provided port
app.listen(port);
console.log('server is listening');


What's going on here is pretty simple:

  • We required and made use of the dependencies
  • We defined and set the API routes
  • We set a port for our server to listen to


The API routes are being required from ./route, but this path does not exist yet. Let's quickly create it.

At the root of the project directory, create a file called route.js. This is where the API routes will be made. We need to have a form of a database from where we can fetch, post, delete, and modify data.

Just as in the previous example, we will make use of diskdb. The route will pretty much have the same pattern as in the first example.

Install diskDB


Run the following in the project folder to install diskdb:

npm install diskdb


Create a users.json file at the root of the project directory to serve as our database collection where we have our users' details.

Populate users.json with the following:

[{"name": "Marcel", "email": "test1@gmail.com", "phone_number":"08012345", "isOnline":false}]


Now, update route.js.

route.js
const express = require('express');
const router = express.Router();
const db = require('diskdb');
db.connect(__dirname, ['users']);
//save
router.post('/users', function(req, res, next) {
var user = req.body;
if (!user.name && !(user.email + '') && !(user.phone_number + '') && !(user.isActive + '')) {
res.status(400);
res.json({
error: 'error'
});
} else {
console.log('ds');
db.users.save(todo);
res.json(todo);
}
});
//get
router.get('/users', function(req, res, next) {
var foundUsers = db.users.find();
console.log(foundUsers);
res.json(foundUsers);
foundUsers = db.users.find();
console.log(foundUsers);
});
//updateUsers
router.put('/user/:id', function(req, res, next) {
var updUser = req.body;
console.log(updUser, req.params.id)
db.users.update({_id: req.params.id}, updUser);
res.json({ msg: req.params.id + ' updated' });
});
//delete
router.delete('/user/:id', function(req, res, next) {
console.log(req.params);
db.users.remove({
_id: req.params.id
});
res.json({ msg: req.params.id + ' deleted' });
});
module.exports = router;


We've created a REST API with the API routes, using diskDB as the database.

Start the server using the following command:

node server.js


The server is running and it is listening to the assigned port. Now, open up the browser and go to http://localhost:3000/api/users.

Here, we can see the data that we imputed to the users.json file. This shows that our routes are working and we are getting data from the database.

Create a new component


Run the following command to create a new component:

ng g component user


This creates user.component.ts, user.component.html, user.component.css and user.component.spec.ts files. User.component.spec.ts is used for testing, therefore we will not be making use of it in this chapter. The newly created component is automatically imported into app.module.ts. We have to tell the root component about the user component. We'll do this by importing the selector from user.component.ts into the root template component (app.component.html):

<div style="text-align:center">
<app-user></app-user>
</div>

Create a service


The next step is to create a service that interacts with the API that we created earlier:

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
ng generate service user


This creates a user service called the user.service.ts. Next, import UserService class into app.module.ts and include it to the providers array:

Import rxjs/add/operator/map in the imports section.
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
Within the UserService class, define a constructor and pass in the angular 2 HTTP service.
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class UserService {
constructor(private http: Http) {}
}


Within the service class, write a method that makes a get request to fetch all users and their details from the API:

getUser() {
return this.http
.get('http://localhost:3000/api/users')
.map(res => res.json());
}


Write the method that makes a post request and creates a new todo:

addUser(newUser) {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http
.post('http://localhost:3000/api/user', JSON.stringify(newUser), {
headers: headers
})
.map(res => res.json());
}


Write another method that makes a delete request. This will enable us to delete a user from the collection of users:

deleteUser(id) {
return this.http
.delete('http://localhost:3000/api/user/' + id)
.map(res => res.json());
}


Finally, write a method that makes a put request. This method will enable us to modify the state of a user:

updateUser(user) {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http
.put('http://localhost:3000/api/user/' + user._id, JSON.stringify(user), {
headers: headers
})
.map(res => res.json());
}


Update app.module.ts to import HttpModule and FormsModule and include them to the imports array:

import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
.....
imports: [
.....
HttpModule,
FormsModule
]


The next thing to do is to teach the user component to use the service:

Import UserService in user.component.ts.
import {UserService} from '../user.service';
Next, include the service class in the user component constructor.
constructor(private userService: UserService) { }.
Just below the exported UserComponent class, add the following properties and define their data types:
users: any = [];
user: any;
name: any;
email: any;
phone_number: any;
isOnline: boolean;


Now, we can make use of the methods from the user service in the user component.

Updating user.component.ts


Within the ngOnInit method, make use of the user service to get all users from the API:

ngOnInit() {
this.userService.getUser().subscribe(users => {
console.log(users);
this.users = users;
});
}


Below the ngOnInit method, write a method that makes use of the post method in the user service to add new users:

addUser(event) {
event.preventDefault();
var newUser = {
name: this.name,
email: this.email,
phone_number: this.phone_number,
isOnline: false
};
this.userService.addUser(newUser).subscribe(user => {
this.users.push(user);
this.name = '';
this.email = '';
this.phone_number = '';
});
}


Let's make use of the delete method from the user service to enable us to delete users:

deleteUser(id) {
var users = this.users;
this.userService.deleteUser(id).subscribe(data => {
console.log(id);
const index = this.users.findIndex(user => user._id == id);
users.splice(index, 1)
});
}


Finally, we'll make use of user service to make put requests to the API:

updateUser(user) {
var _user = {
_id: user._id,
name: user.name,
email: user.email,
phone_number: user.phone_number,
isActive: !user.isActive
};
this.userService.updateUser(_user).subscribe(data => {
const index = this.users.findIndex(user => user._id == _user._id)
this.users[index] = _user;
});
}


We have all our communication with the API, service, and component. We have to update user.component.html in order to illustrate all that we have done in the browser.

We'll be making use of bootstrap for styling. So, we have to import the bootstrap CDN in index.html:

<!doctype html>
<html lang="en">
<head>
//bootstrap CDN
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<meta charset="utf-8">
<title>User</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

Updating user.component.html


Here is the component template for the user component:

<form class="form-inline" (submit) = "addUser($event)">
<div class="form-row">
<div class="col">
<input type="text" class="form-control" [(ngModel)] ="name" name="name">
</div>
<div class="col">
<input type="text" class="form-control" [(ngModel)] ="email" name="email">
</div>
<div class="col">
<input type="text" class="form-control" [(ngModel)] ="phone_number" name="phone_number">
</div>
</div> <br>
<button class="btn btn-primary" type="submit" (click) = "addUser($event)"><h4>Add User</h4></button>
</form>
<table class="table table-striped" >
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone_Number</th>
<th>Active</th>
</tr>
</thead>
<tbody *ngFor="let user of users">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
<td>{{user.phone_number}}</td>
<td>{{user.isActive}}</td>
<td><input type="submit" class="btn btn-warning" value="Update Status" (click)="updateUser(user)" [ngStyle]="{ 'text-decoration-color:': user.isActive ? 'blue' : ''}"></td>
<td><button (click) ="deleteUser(user._id)" class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>


A lot is going on in the preceding code, let's drill down into the code block:

  • We have a form which takes in three inputs and a submit button which triggers the addUser() method when clicked
  • There is a delete button which triggers the delete method when it is clicked
  • There is also an update status input element that triggers the updateUser() method when clicked
  • We created a table in which our users' details will be displayed utilizing Angular's *ngFor directive and Angular's interpolation binding syntax, {{}}


Some extra styling will be added to the project. Go to user.component.css and add the following:

form{
margin-top: 20px;
margin-left: 20%;
size: 50px;
}
table{
margin-top:20px;
height: 50%;
width: 50%;
margin-left: 20%;
}
button{
margin-left: 20px;
}

Running the app


Open up two command line interfaces/terminals. In both of them, navigate to the project directory. Run node server.js to start the server in one. Run ng serve in the other to serve the Angular 2 app.

Open up the browser and go to localhost:4200.

In this simple users app, we can perform all CRUD operations. We can create new users, get users, delete users, and update the state of users.

By default, a newly added user's active state is false. That can be changed by clicking on the change state button.

We created an Angular app from scratch for building a user directory. To know more, on how to write unit tests and perform debugging in Angular, check our book TypeScript 2.x for Angular Developers.

Everything new in Angular 6: Angular Elements, CLI commands and more
Why switch to Angular for web development – Interview with Minko Gechev
Building Components Using Angular