Angular - Observer Pattern



This chapter will discuss the Observer Pattern in Angular, its advantages, and its complete implementation with an appropriate example that will give you a clear understanding. The Observer Pattern from the RxJS library is used to synchronize the fetched data on the screen.

What is RxJS?

The RxJS is a library that stands for Reactive Extensions JavaScript. It allows you to work with the synchronized data stream.

It is used for "reactive programming", which is a way to develop an application that reacts to changes instead of explicitly writing code to handle them.

What is Observer Pattern in Angular?

In Angular, the Observer Pattern is a design pattern that allows an object to called the observable from RxJS library to send notifications to multiple observer objects that are interested in the state changes of the observable. This design pattern is useful in managing asynchronous data streams in Angular applications.

The following diagram of the observer pattern will provide you with a clear understanding of how the "publisher" (service) returns the "observable". The "observable" emits data, and the "subscriber" subscribes to the data to react to changes or updates.

Obser pattern

Note: You can have multiple subscribers listening to the same observable

Here,

  • The publisher is a service that generates data or events. It is responsible for creating and maintaining the Observable.
  • The observable is an entity that emits the data or events. It represents the data stream that other components can subscribe to.
  • The subscription is a process by which other components subscribe to the Observable to receive updates. Each subscriber gets notified whenever the Observable emits new data.
  • The subscriber is a component that subscribes and reacts to the data emitted by the Observable.

Advantages of Observer Pattern

Following is a list of advantages of the Angular Observer Pattern

  • Reactive Programming
  • Event Handling
  • Error Handling
  • Improved Testablity

Implementation

Follow the process below to implement the observer pattern in an Angular application:

Application Setup

Let's set up an angular application using CLI (command line interace) to implement the observer pattern from scratch within this newly created application.

Use the steps given below to create a new Angular application:

Step 1: Open the node.js command or code editor (e.g., VS code) terminal and go to your favorite workspace as:

cd /favourite/workspace/ folder_name

Step 2: Install Angular CLI using the following command (see more):

npm install @angular/cli

Step 3: Create a new angular application, myApp as follows:

ng new myApp

Note: Once you hit the above command, it will ask you a few questions and reply with the default answers.

Step 4: Open the AppComponent (app.component.html) file remove everything and place the code below:

<h2>Welcome to Angular Observer Design Pattern</h2>

Step 5: Navigate to your "application directory" as:

cd myApp

Step 6: Run the application to verify it is created successfully:

ng serve

Step 7: Open your preferred browser (e.g., chrome) and navigate to localhost:4200 URL to see the output:

observer pattern

Create Observable Service

Let's create an Observable service to implement the Observable from the RxJS library. This service will allow you to share data across different components in the application.

Step 1: Create a service, observer, as follows:

ng generate service observer

Once the above command is executed successfully, you might be able to see "two new files" within your application:

observer pattern

Here,

  • The first file, observer.service.spec.ts, is a unit testing file (we typically do not make changes in this file).
  • The second file, observer.service.ts, is where we write all the "logic" and "functionalities".

Implement Observable in Service

We will define a method, getRandColors() within the service class, which returns an observable. This method will pick and return a random color from the given array when this method is called in the component each time.

Step 1: Open the observer.service.ts file in your code editor and implement the getRandColors() method:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

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

  constructor() { }

  getRandColors(): Observable<string> { 
    return new Observable<string>(observer => { 
      let colors = ["red", "green", "black", "yellow", "blue", "pink", "gray"]; 
      let rand = Math.floor(Math.random() * colors.length); 
      observer.next(colors[rand]);
      observer.complete(); });
    }
}

Note: To work with the Observable pattern, make sure the RxJS library is imported into your service class.

Use the Observable Service in Component

As we have implemented the observable in the service class, we will now use the observable service within our root component to access its methods to retrieve the observer value.

Step 1: Open the app.component.ts file, import, and inject the observable service.

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { ObserverService } from './observer.service';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent{
  constructor(private myService: ObserverService) {}
}

Step 2: As the service is already injected via Dependency Injection, now define a method, changeBackground(), access the service method within it, and assign the returned color value to the variable background:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { ObserverService } from './observer.service';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent{
  constructor(private myService: ObserverService) {}
  //variable to store the color
  background: any;
  changeBackground(){
    this.myService.getRandColors().subscribe(color =>{
	//assigning value
      this.background = color;
    });
  }
}

Update the Template

Now, let's update the template (app.component.html) to display the observer value initially when the component loads and update it dynamically when the value changes.

Step 1: Open the app.component.html file in your code editor, bind the background variable with the div element using style binding, and create a button to change the background on click:

<div [ngStyle]="{background: background}">
    <h2>Welcome to Angular Observer Design Pattern</h2>
    <button (click)="changeBackground()">Change Background</button>
    <p>Color (Observer value): {{background}}</p>
</div>

Step 2: Open the app.component.css file and place the given code below in it:

div{
    height: 95vh;
    padding: 0;
    margin: 0;
    font-family: sans-serif;
    color: rgb(32, 76, 76);
    padding: 10px;
}
button{
    padding: 15px 50px;
    cursor: pointer;
    background-color: antiquewhite;
    border: 1px solid white;
    color: rgb(30, 76, 11);
    border-radius: 5px;
    font-weight: bold;
    font-size: 18px;
}

Display the Observer value in Template

We have used the observable service in our app component. Now, let's run the application to display the observer value in the template.

Step 1: Run the application using the following command:

ng serve

Step 2: Open your preferred browser (e.g., Chrome) and navigate to the http://localhost:4200 URL.

Once you navigate to the above URL, you will be able to see the following:

observer pattern

Conclusion

In conclusion, the Angular observer design pattern is a powerful approach for managing data flow and communication between different parts of an application. This is widely applied in the Angular application and with RxJS, we can elegantly sync the fetched data on the screen. Although starting from Angular 17.2, the RxJS becomes optional and were moving to the signals, its still a good way to learn and apply the observer pattern in Angular.

Advertisements