Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

rxjs operators in angular services

Suggested Videos
Part 23 - Angular dynamic forms validation | Text | Slides
Part 24 - Angular formarray validation | Text | Slides
Part 25 - Remove dynamically created form controls in angular | Text | Slides

Angular 6 uses rxjs 6. You can verify this by looking at package.json file in your Angular 6 project. In this video we will discuss using rxjs 6 operators in Angular 6 services.


In the project that we have been working with so far in this video tutorial, we need to do some ground work before we we can create an angular service. 


Creating a fake online REST API

First let's create a fake online REST API. For this we are going to use JSON-Server. We discussed what REST API is and using JSON-server in Part 63 of Angular CRUD tutorial.

The following is the JSON Server Github page 
https://github.com/typicode/json-server

Execute the following NPM command to install JSON server

npm install -g json-server 

Create db.json file in the root project folder. Copy and paste the following JSON data in the file.

{
    "employees": [
        {
            "id": 1,
            "fullName": "Mark",
            "contactPreference": "email",
            "email": "mark@email.com",
            "phone": "5641238971",
            "skills": [
                {
                    "skillName": "C#",
                    "experienceInYears": 1,
                    "proficiency": "beginner"
                },
                {
                    "skillName": "Java",
                    "experienceInYears": 2,
                    "proficiency": "intermediate"
                }
            ]
        },
        {
            "id": 2,
            "fullName": "John",
            "contactPreference": "phone",
            "email": "john@email.com",
            "phone": "3242138971",
            "skills": [
                {
                    "skillName": "Angular",
                    "experienceInYears": 2,
                    "proficiency": "beginner"
                },
                {
                    "skillName": "HTML",
                    "experienceInYears": 2,
                    "proficiency": "intermediate"
                },
                {
                    "skillName": "LINQ",
                    "experienceInYears": 3,
                    "proficiency": "advanced"
                }
            ]
        }
    ]
}

Execute the following command to start the server

json-server --watch db.json

At this point, fire up the browser and navigate to http://localhost:3000/employees/ to see the list of all employees along with their skills. You can test this REST API using a tool like fiddler. 

Creating the required interfaces to represent Employee and Skill types

Add a file in the employee folder with name ISkill.ts. Copy and paste the following code.

export interface ISkill {
    skillName: string;
    experienceInYears: number;
    proficiency: string;
}

Add a file in the employee folder with name IEmployee.ts. Copy and paste the following code.

import { ISkill } from './ISkill';

export interface IEmployee {
    id: number;
    fullName: string;
    email: string;
    phone?: number;
    contactPreference: string;
    skills: ISkill[];
}

Creating Angular Service

Add a file in the employee folder with name employee.service.ts. Copy and paste the following code.

import { Injectable } from '@angular/core';
import { IEmployee } from './IEmployee';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';

import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class EmployeeService {
    baseUrl = 'http://localhost:3000/employees';
    constructor(private httpClient: HttpClient) {
    }

    getEmployees(): Observable<IEmployee[]> {
        return this.httpClient.get<IEmployee[]>(this.baseUrl)
            .pipe(catchError(this.handleError));
    }

    private handleError(errorResponse: HttpErrorResponse) {
        if (errorResponse.error instanceof ErrorEvent) {
            console.error('Client Side Error :', errorResponse.error.message);
        } else {
            console.error('Server Side Error :', errorResponse);
        }
        return throwError('There is a problem with the service. We are notified & working on it. Please try again later.');
    }

    getEmployee(id: number): Observable<IEmployee> {
        return this.httpClient.get<IEmployee>(`${this.baseUrl}/${id}`)
            .pipe(catchError(this.handleError));
    }

    addEmployee(employee: IEmployee): Observable<IEmployee> {
        return this.httpClient.post<IEmployee>(this.baseUrl, employee, {
            headers: new HttpHeaders({
                'Content-Type': 'application/json'
            })
        })
        .pipe(catchError(this.handleError));
    }

    updateEmployee(employee: IEmployee): Observable<void> {
        return this.httpClient.put<void>(`${this.baseUrl}/${employee.id}`, employee, {
            headers: new HttpHeaders({
                'Content-Type': 'application/json'
            })
        })
            .pipe(catchError(this.handleError));
    }

    deleteEmployee(id: number): Observable<void> {
        return this.httpClient.delete<void>(`${this.baseUrl}/${id}`)
            .pipe(catchError(this.handleError));
    }
}

RxJS 5 vs 6

An Angular 6 project, by default uses RxJS version 6. RxJS 6 has some breaking changes compared to RxJS 5.5 and older versions.

The way we import some of the classes like Observable and Subject has changed in RxJS 6.

In RxJS 5, we import Observable and Subject classes as shown below.

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

In RxJS 6, this has changed to

import { Observable, Subject } from 'rxjs';

Similarly, the way we import operators also changed in RxJS 6. To import catchError operator in RxJS 5, we use the following

import { catchError } from 'rxjs/operators/catchError';

In RxJS 6, it has changed to the following

import { catchError } from 'rxjs/operators';

In RxJS 6, we import all the operators from 'rxjs/operators'

import { map, delay, catchError } from 'rxjs/operators';

Many classes like ArrayObservable, EmptyObservable, ErrorObservable etc are also removed from v6, in favour of existing or new operators that perform the same operations.

For example, in v5 to create an ErrorObservable we might use one of the following

new ErrorObservable('Your error message');

OR

ErrorObservable.create('Your error message');

In v6, we use throwError() function to achieve this. 

return throwError('Your error message');

How do I know, I have to use throwError() function instead of ErrorObservable class. Well, the following GitHub article contains all the differences between RxJS v5.x and v6. A quick search (CTRL + F) on the page for ErrorObservable shows, it has been removed in favour of throwError() function.
https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md

in v6, import throwError function from rxjs. Since ErrorObservable class is replaced by throwError function, we import it the same way we import other classes like Observable and Subject from rxjs.

import { Observable, throwError } from 'rxjs';

Implementing ListEmployeesComponent : While we are here, let's implement ListEmployeesComponent

We want this component to display all employee details as shown below.

angular list component example

Copy and paste the following HTML in list-employees.component.html

<div class="table-responsive">
  <table class="table table-bordered" *ngIf="employees && employees.length">
    <thead>
      <tr class="bg-primary">
        <th>Name</th>
        <th>Email</th>
        <th>Phone</th>
        <th>Contact Preference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let employee of employees">
        <td>{{ employee.fullName }}</td>
        <td>{{ employee.email }}</td>
        <td>{{ employee.phone }}</td>
        <td>{{ employee.contactPreference }}</td>
        <td> <button class="btn btn-primary">Edit</button> </td>
      </tr>
    </tbody>
  </table>
</div>

Copy and paste the following code in list-employees.component.ts

import { Component, OnInit } from '@angular/core';
import { EmployeeService } from './employee.service';
import { IEmployee } from './IEmployee';

@Component({
  selector: 'app-list-employees',
  templateUrl: './list-employees.component.html',
  styleUrls: ['./list-employees.component.css']
})
export class ListEmployeesComponent implements OnInit {
  employees: IEmployee[];

  constructor(private _employeeService: EmployeeService) { }

  ngOnInit() {
    this._employeeService.getEmployees().subscribe(
      (employeeList) => this.employees = employeeList,
      (err) => console.log(err)
    );
  }

}

Changes in app.module.ts file

To be able to use EmployeeService in ListEmployeesComponent we have to register it. Since we want EmployeeService to be available across the entire application, Let's register it in the application root module AppModule.

Import EmployeeService and include it in the providers array of @NgModule decorator of AppModule. Employee service uses angular's HttpClient service. To be able to use this we have to import HttpClientModule in the AppModule and include it in the imports array.

import { EmployeeService } from './employee/employee.service';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    CreateEmployeeComponent,
    ListEmployeesComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ReactiveFormsModule
  ],
  providers: [EmployeeService],
  bootstrap: [AppComponent]
})
export class AppModule { }

angular 6 tutorial for beginners

2 comments:

  1. i am getting the error "Type 'Subscription' is missing the following properties from type 'Employee[]': length, pop, push, concat, and 26" in the ngOnInit where the call to the service is made

    ReplyDelete
  2. Best Resource of Learning the Knowledge they provide

    ReplyDelete

It would be great if you can help share these free resources