Support us .Net Basics C# SQL ASP.NET ADO.NET MVC Slides C# Programs Subscribe Buy DVD

Create observable from array

Suggested Videos
Part 50 - Data filter in angular component | Text | Slides
Part 51 - Angular query params | Text | Slides
Part 52 - Angular read query string parameters | Text | Slides

In this video we will discuss, how to create an observable from static data in an array. Along the way, we will discuss, the 2 most common issues that you will run into when working with observables in your angular application.


There are several ways to create an observable. The simplest of all is to use Observable.of() as shown below.


import { Injectable } from '@angular/core';
import { Employee } from '../models/employee.model';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

@Injectable()
export class EmployeeService {

    private listEmployees: Employee[] = [
        { id: 1, name: 'Mark' },
        { id: 2, name: 'Mary' },
        { id: 3, name: 'John' },
    ];

    getEmployees(): Observable<Employee[]> {
        return Observable.of(this.listEmployees);
    }
}

At this point, you might be wondering why do we have to return an Observable<Employee[]> instead of just an Employee[] from getEmployees() method. Well, this is because in a real world application, we would not have data hard coded like this in the angular service. We retrieve it from a database by calling a server side service using the angular http service. The angular http service returns an observable. 

We discussed Observables and calling server side service using the angular HTTP service in Part 27 of Angular 2 tutorial

In our upcoming videos in this series, we will discuss calling a server side service. So in preparation for that, we are creating and returning an Observable

In a typical real world application, when a server side service is called over HTTP, there may be some latency and we may not get the data immediately. So to simulate some artificial latency and understand the implications it can have on the code that consumes this returned Observable, import and use the delay operator as shown below. Notice we have a delay of 2000 milli-seconds.

import 'rxjs/add/operator/delay';

getEmployees(): Observable<Employee[]> {
    return Observable.of(this.listEmployees).delay(2000);
}

Consider the following code which calls getEmployees() method of EmployeeService. If you are following along with this course, the following code is from ListEmployeesComponent class in list-employees.component.ts. The code is commented and self explanatory.

ngOnInit() {
  this._employeeService.getEmployees().subscribe((empList) => {
    // This code executes asynchronously. When the data is returned
    // after the 2 seconds delay, that's when the employees property is set
    this.employees = empList;
  });

  // This code will not wait for 2 seconds. After a call to the subscribe() method
  // is issued, the application continues to process the below lines of code. So for
  // those 2 seconds this.employees property is undefined, and with in that time, the
  // below code is executed which can have 2 serious implications
  // 1. The list page will not display any data
  // 2. Cannot read property 'length' of undefined error in the console
  this._route.queryParamMap.subscribe(params => {
    if (params.has('searchTerm')) {
      this.searchTerm = params.get('searchTerm');
    } else {
      this.filteredEmployees = this.employees;
      console.log(this.employees.length);
    }
  });
}

To fix these 2 issues, we want the second block of code to execute synchronously after the employees property is populated with data returned from the service. To achieve this move the second block of code, into the callback function passed as a parameter to the subscribe() method.

ngOnInit() {
  this._employeeService.getEmployees().subscribe((empList) => {
    this.employees = empList;
    this._route.queryParamMap.subscribe(params => {
      if (params.has('searchTerm')) {
        this.searchTerm = params.get('searchTerm');
      } else {
        this.filteredEmployees = this.employees;
        console.log(this.employees.length);
      }
    });
  });
}

At this point, when you navigate to the list route, only a part of the page loads first and after 2 seconds when the data becomes available that's when the page is updated with employee list. You don't want to display a partial page to the user, while waiting for the data. We will discuss how to fix this using the resolve guard in our next video.

angular crud tutorial

No comments:

Post a Comment

If you like this website, please share with your friends on facebook and Google+ and recommend us on google using the g+1 button on the top right hand corner.