Consuming REST API with Angular

Hello folks, what’s up! In this tutorial we’re going to build front-end to consume REST API that we’ve developed in our previous tutorial. If you haven’t have any familiarity with angular, then I highly recommend you to go through this tutorial.

Now let’s start building our Angula App to consume REST API. Start with a command

Consuming REST API with Angular

ng new angular

This command will create an angular-project named angular, after that you can do something like this to run you app:

cd angular
ng s

By default, your angular app will run in port 8080 and it will look something like this:

Building Angular App

You’ve successfully created angular app; creating angular app is really easy, isn’t it? But this is not our goal, we want to create app consuming REST API and performing CRUD operation with the back-end that we’d developed in earlier tutorial.

So let’s ready to have some code.

Let’s start with defining some constants. Inside environments -> environment.ts insert the following code:

export const environment = {
  production: false,
  API_ENDPOINT: 'http://localhost:8080/employees'
};

We’re giving the endpoint for out back-end. Then create a folder named constants inside src -> app and create the following ts files; api-constants.ts and app-routes.ts

import { environment } from 'src/environments/environment';

export class ApiConstants {
    public static API_ENDPOINT = environment.API_ENDPOINT;
}
export class AppRoutes {
    public static employees = 'dashboard';
    public static roles = 'roles';
    public static view = 'view';
    public static edit = 'edit/:id';
    public static add = 'add';
}

Then create a folder src -> app -> shared and inside shared folder create two model classes employee-model.ts and role-model.ts and as well as create a employeeService by using the command:

ng g service shared/employeeService

Then insert the following code respectively:

import { RoleModel } from './role-model';

export class EmployeeModel {
    id: number;
    empAddress: string;
    empName: string;
    empAge: number;
    role: RoleModel;
}
export class RoleModel {
    id: number;
    roleDesc: string;
    roleName: string;
}
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ApiConstants } from '../constants/api-constants';
import { EmployeeModel } from './employee-model';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':  'application/json'
  })
};

@Injectable({
  providedIn: 'root'
})
export class EmployeesService {

  constructor(private http: HttpClient) { }

  getAllEmployee() {
    return this.http
        .get(ApiConstants.API_ENDPOINT)
        .toPromise()
        .then(this.handleSuccess)
        .catch(this.handleError);
  }

  getAllRoles() {
    return this.http
        .get(ApiConstants.API_ENDPOINT + "/role")
        .toPromise()
        .then(this.handleSuccess)
        .catch(this.handleError);
  }

  getEmployeeById(id) : Promise<any> {
    return this.http
              .get(ApiConstants.API_ENDPOINT + "/" + id)
              .toPromise()
              .then(this.handleSuccess)
              .catch(this.handleError);
  }

  edit(employee: EmployeeModel, id): Promise<any> {
    return this.http
            .put(
              ApiConstants.API_ENDPOINT + "/" + id, employee
            )
            .toPromise()
            .then(this.handleSuccess)
            .catch(this.handleError);
  }

  delete(id): Promise<any> {
    return this.http
            .delete(
              ApiConstants.API_ENDPOINT + "/" + id
            )
            .toPromise()
            .then(this.handleSuccess)
            .catch(this.handleError);
  }

  add(employee: EmployeeModel) {
    return this.http
              .post(
                ApiConstants.API_ENDPOINT, employee, httpOptions
              )
              .toPromise()
              .then(this.handleSuccess)
              .catch(this.handleError);
              
  }

  private handleSuccess(successResponse): Promise<any> {
    return Promise.resolve(successResponse);
  }

  private handleError(errorResponse): Promise<any> {
    return Promise.reject(errorResponse);
  }
}

While writing the above code, you’ll require some http dependency, you can google it and install it. Actually, I’ve forgotten what dependencies I’d installed 🙂 . Anyway, we’re concerned with consuming REST API’s so let’s move ahead.

Creating a component add, edit and view inside src -> app by using the below commands:

ng g component add
ng g component edit
ng g component view

Now our project structure is almost complete. So now we include the code into the classes directly.

Include the following code inside app-routing.model.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppRoutes } from './constants/app-routes';
import { EditComponent } from './edit/edit.component';
import { ViewComponent } from './view/view.component';
import { AddComponent } from './add/add.component';

const routes: Routes = [
  {
    path: '',
    component: ViewComponent,
    pathMatch: 'full'
  },
  {
    path: AppRoutes.edit,
    component: EditComponent,
    pathMatch: 'full'
  },
  {
    path: AppRoutes.add,
    component: AddComponent,
    pathMatch: 'full'
  }

];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Your app.module.ts should look like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { RolesComponent } from './roles/roles.component';
import { EmployeesService } from './shared/employees.service';
import { AppRoutingModule } from './app-routing.model';
import { HttpClientModule } from '@angular/common/http';
import { ToastrModule } from 'ngx-toastr';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { EditComponent } from './edit/edit.component';
import { ViewComponent } from './view/view.component';
import { FormsModule } from '@angular/forms';
import { AddComponent } from './add/add.component';


@NgModule({
  declarations: [
    AppComponent,
    RolesComponent,
    EditComponent,
    ViewComponent,
    AddComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ToastrModule.forRoot(),
    BrowserAnimationsModule,
    FormsModule
  ],
  providers: [EmployeesService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Inside app.component.html include:

<router-outlet></router-outlet>

This tag is for routing purpose. If you’re familiar with angular, then you will surely know about this.

Now lets fill the code for out view component.

Inside view.component.html include following code:

<table class="table table-minimal-border">
  <thead>
      <tr>
          <!-- <th>ID</th> -->
          <th>Employee Name</th>
          <th>Employee Age</th>
          <th>Employee Address</th>
          <th>Employee Role Name</th>
          <th>Edit</th>
      </tr>
  </thead>
  <tbody striped="true">
      <tr *ngFor="let employee of employees">
          <!-- <td>{{metatable.id ? metatable.id :'N/A' }}</td> -->
          <td>{{employee.empName ? employee.empName : 'N/A'}}</td>
          <td>{{employee.empAge ? employee.empAge : 'N/A'}}</td>
          <td>{{employee.empAddress ? employee.empAddress : 'N/A'}}</td>
          <td>{{employee.role.roleName ? employee.role.roleName : 'N/A'}}</td>
          <td>
              <button type="button" [routerLink]="['edit',employee.id]">Edit Employee</button>
          </td>
          <td>
            <button type="button" (click)="delete(employee.id)">Delete Employee</button>
          </td>
      </tr>
      <button type="button" [routerLink]="['add']">Add Employee</button>
  </tbody>
</table>

Inside view.component.ts include following code:

import { Component, OnInit } from '@angular/core';
import { EmployeeModel } from '../shared/employee-model';
import { EmployeesService } from '../shared/employees.service';
import { ToastrService } from 'ngx-toastr';
import { Location } from '@angular/common';

@Component({
  selector: 'app-view',
  templateUrl: './view.component.html',
  styleUrls: ['./view.component.css']
})
export class ViewComponent implements OnInit {

  employees: Array<EmployeeModel> = [];

  constructor(private employeeService: EmployeesService,
    private toastr: ToastrService,
    private location: Location) { }

  ngOnInit() {
    this.getAllEmployees();
  }
  getAllEmployees(): any {
    this.employeeService
      .getAllEmployee()
      .then(successResponse => {
        this.employees = successResponse;

      })
      .catch(errorResponse => {
        this.toastr.error(errorResponse.error.message)
      })
  }

  delete(id : any) {
    this.employeeService
      .delete(id)
      .then(successResponse => {
        this.getAllEmployees();
      })
      .catch();
  }

}

After that, let’s fill out the code for add component.

Inside add.component.html include the following code:

<div class="animated fadeIn">
  <div class="row">
    <div class="col-md-12">
      <div class="page-title-wrapper">
        <div class="row">
          <div class="col-md-12">
            <div class="back-button-block">
              <button type="button" (click)="back()" class="btn btn-icon-only casba-bck-btn">
                <i class="mdi mdi-arrow-left" aria-hidden="true"></i>
              </button>
            </div>
            <div class="page-title-block">
              <div class="page-title">
                <span>Add Employee</span>
              </div>

            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-md-12">
      <div class="card">
        <div class="card-body">
          <form #addEmployee="ngForm" class="form-horizontal" (submit)="add(addEmployee)" novalidate>
            <div class="row">
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Name</label>
                  <div class="input-group">
                    <input type="text" id="empName" name="empName" class="form-control" [(ngModel)]="employee.empName">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Age</label>
                  <div class="input-group">
                    <input type="text" id="empAge" name="empAge" class="form-control" [(ngModel)]="employee.empAge">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Address</label>
                  <div class="input-group">
                    <input type="text" id="empAddress" name="empAddress" class="form-control"
                      [(ngModel)]="employee.empAddress">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <span>Select Role</span>
                <div>
                  <select name="employeeRole" [(ngModel)]="employee.role">
                    <option *ngFor="let role of roles" [ngValue]="role">{{role.roleName}}</option>
                  </select>
                </div>
              </div>
            </div>
            <div class="admin-card-footer">
              <button *ngIf="!buttonPressed" type="submit" class="btn btn-gap btn-primary">Add</button>
              <button *ngIf="!buttonPressed" type="button" class="btn btn-default" (click)="back()">Cancel</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>

And in add.component.ts, include following component:

import { Component, OnInit } from '@angular/core';
import { EmployeeModel } from '../shared/employee-model';
import { EmployeesService } from '../shared/employees.service';
import { Location } from '@angular/common';
import { RoleModel } from '../shared/role-model';

@Component({
  selector: 'app-add',
  templateUrl: './add.component.html',
  styleUrls: ['./add.component.css']
})
export class AddComponent implements OnInit {

  employee: EmployeeModel = new EmployeeModel();
  roles:Array<RoleModel> = [];
  selectedRole: RoleModel = new RoleModel();
  constructor(
    private employeeService: EmployeesService,
    private location: Location
  ) { }

  ngOnInit() {
    this.getRole();
  }
  getRole(): any {
    this.employeeService
        .getAllRoles()
        .then(successResponse => {
          this.roles = successResponse;
        })
        .catch(errorResponse => {

        });
  }

  add(employee: any) {
    this.employeeService
      .add(this.employee)
      .then(successResponse => {
          this.location.back();
      })
      .catch(errorResponse => {

      });
  }

  back() {
    this.location.back();
  }

}

Finally for edit component, add the following codes:

Inside edit.component.html

<div class="animated fadeIn">
  <div class="row">
    <div class="col-md-12">
      <div class="page-title-wrapper">
        <div class="row">
          <div class="col-md-12">
            <div class="back-button-block">
              <button type="button" (click)="back()" class="btn btn-icon-only casba-bck-btn">
                <i class="mdi mdi-arrow-left" aria-hidden="true"></i>
              </button>
            </div>
            <div class="page-title-block">
              <div class="page-title">
                <span>Edit Employee</span>
              </div>

            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-md-12">
      <div class="card">
        <div class="card-body">
          <form #editEmployee="ngForm" class="form-horizontal" (submit)="edit(employee.id, editEmployee)" novalidate>
            <div class="row">
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Name</label>
                  <div class="input-group">
                    <input type="text" id="empName" name="empName" class="form-control" [(ngModel)]="employee.empName">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Age</label>
                  <div class="input-group">
                    <input type="text" id="empAge" name="empAge" class="form-control" [(ngModel)]="employee.empAge">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Address</label>
                  <div class="input-group">
                    <input type="text" id="empAddress" name="empAddress" class="form-control"
                      [(ngModel)]="employee.empAddress">
                  </div>
                </div>
              </div>
              <div class="col-md-4">
                <div class="form-group">
                  <label for="fieldName">Employee Role Name</label>
                  <div class="input-group">
                    <input type="text" id="id" name="id" class="form-control" value="{{employee.role.roleName}}"
                      readonly>
                  </div>
                </div>
              </div>

              <div class="col-md-4">
                <span>Select Role</span>
                <div>
                  <select name="employeeRole" [(ngModel)]="employee.role">
                    <option *ngFor="let role of roles" [ngValue]="role">{{role.roleName}}</option>
                  </select>
                </div>
              </div>

            </div>
            <div class="admin-card-footer">
              <button *ngIf="!buttonPressed" type="submit" class="btn btn-gap btn-primary">Modify</button>
              <button *ngIf="!buttonPressed" type="button" class="btn btn-default" (click)="back()">Cancel</button>
              <button *ngIf="buttonPressed" class="btn btn-default" [disabled]="true">Processing</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>

and inside edit.component.ts

import { Location } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { EmployeeModel } from '../shared/employee-model';
import { EmployeesService } from '../shared/employees.service';
import { RoleModel } from '../shared/role-model';

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {
  id: number;
  employee: EmployeeModel = new EmployeeModel();
  roles: Array<RoleModel> = [];
  constructor(
    private employeeService: EmployeesService,
    private toastr: ToastrService,
    private route: ActivatedRoute,
    private location: Location) { }

  ngOnInit() {
    this.getEmployeeForEdit();
    this.getAllRoles();
  }
  getAllRoles(): any {
    this.employeeService
      .getAllRoles()
      .then(successResponse => {
        this.roles = successResponse;
      })
      .catch(errorResponse => {

      });
  }

  getEmployeeForEdit() {
    this.id = this.route.snapshot.params.id;
    if (this.id) {
      this.employeeService
        .getEmployeeById(this.id)
        .then(response => {
          this.employee = response;
        })
        .catch(errorResponse => {
          this.toastr.error(errorResponse.error);
        });
    }
  }

  edit(id: number, form: NgForm) {
    this.employeeService
      .edit(this.employee, id)
      .then(successResponse => {
        this.location.back();
      })
      .catch(errorResponse => {
        this.toastr.error(errorResponse.error)
      });
  }

  back() {
    this.location.back();
  }

}

Now finally you can run the application with the following command:

ng s

Note: you mayn’t get design as shown in the screenshots, because its up to you to use different design dependencies. Also there can be some dependencies not found issues, just do google and you’ll find solutions to your every problem. Trust this guy StackOverFlow 😀