Introduction To Subject In Angular 2

Posted By : Satwinder Singh | 16-Mar-2018

Introduction to Subject()

In the official documentation of Rxjs package which we can find at reactivex.io/rxjs/ if we visit the Observable section, we find much more ways of creating Observable such as create(), interval() etc and we can also create an Observable of an existing Promise or we can create it of an event and much more. The Rxjs package offers a lot of operators which we can add to our Observable to transform the data we get back from the Observable. There is another Object in Rxjs package which we can use known as Subject. A Subject basically is like an Observable but it allows us to conveniently push it to emit a new data during our code.

 

Using Subject in our Angular app

To use Subject in our app, first we must create a new service file and name it user.service.ts file (or we can name anything else as per our requirement). In this service, firstly we will create a new property userActivated which will be assigned as a new Subject. We need to import the Subject from ‘ rxjs/Subject ’. Now, this Subject which we create here allows us to do many things but before going any further we must first provide our service in our providers array in the app.module.ts if it is not there i.e. if we are creating the service manually.
user.service.ts file:

import Subject from ‘ rxjs/Subject ’ ;

export class UsersService{
    userActivated = new Subject() ;
}

Now in the user.component.html file which we can use to load an individual user we can say, we will create a button which will be executing onActivate() method on clicking that button.
user.component.html file:

<p>User with <strong> ID {{ id }} </strong> was loaded </p>
<button class="btn btn-primary" (click)="onActivate()"> Activate! </button>

In the typescript file i.e. user.component.ts file, we will implement this method and here we will use our UserService by injecting this service in the constructor() in the user.component.ts file and binding it to some property name, let’s say usersService. We don’t need to provide our service here as we have already provided in the app.module.ts file. Now we can use our usersService property in the onActivate method and call next method and pass the value of user id as an argument in the next() method. A Subject is an Object which can be used as an Observable and Observer at the same time. So with this setup we are kind of pushing a new data package which contains this id.
user.component.ts file:

import { Component , OnInit } from ‘ @angular/core ’ ;
import { UsersService } from ‘ ../users.service’ ;

@Component({
selector: ‘ app-user ’ ,
templateUrl: ‘ ./user.component.html’ ,
styleUrls: [ ‘./user.component.css’ ]
})

export class UserComponent implements OnInit{
id: number;

constructor( private usersService: UsersService){ }
onActivate(){
this.usersService.userActivated.next(this.id) ;
}
}

Let’s say in the AppComponent we want to display ‘Activated’ after the user if the user was activated. So, we will use string interpolation here to check whether the user was activated and then display some text. So here we will set two properties namely user1Activated and user2Activated which will be used to check if the user was activated and display a string ‘activated’ otherwise display an empty string ‘ ’. This is a very rough approach to implementing such a functionality but we are using this approach only to demonstrate the use of the Subject.
app.component.html file:

<div class="container">
    <div class="row">
        <div class="col-xs-12">
            <a routerLink="/" >Home</a>
            <a [routerLink]="[‘user’ , 1]" >
            User1 {{ user1Activated ? ‘ (activated) ’ : ‘ ’ }} 
            </a>
            <a [routerLink]="[‘user’ , 2]">
            User2 {{ user2Activated ? ‘ (activated) ’ : ‘ ’ }} 
            </a>
        </div>
    </div>
</div>
<hr>
<div class="row">
    <div class="col-xs-12">
        <router-outlet></router-outlet>
    </div>
</div>

We will add these two properties user1Activated and user2Activated in our app.component.ts file and set these properties to false in the beginning.We want to use our service here in which we set up our Subject(), so we will inject the UsersService in the app.component.ts file. Now we implement the OnInit method and in the OnInit method we will use our userActivated Subject and subscribe to it and therefore in it we can simply use the data i.e. the ‘ id ’ and check the id of the user to set the respective property to true.
app.component.ts file:

import { Component , OnInit } from ‘ @angular/core ’ ;
import { UsersService } from ‘ ../users.service’ ;

@Component({
   // component declarations go here
})

export class AppComponent implements OnInit{
user1Activated = false ;
user2Activated = false ;

constructor( private usersService:UsersService){}

ngOnInit{
this.usersService.userActivated.subscribe(
(id : number) =>{
 if( id === 1){
this.user1Activated = true ;
}else if( id === 2){
this.user2Activated = true ;
}
}
);
}
}

Now if we go to our working app, we will see that whenever we click Activate button, the user on which we are currently on gets activated. So, therefore we are using a Subject() to have Observable and Observer in one convenient Object. It is kind of comparable to the EventEmitter() which ships with angular and actually the EventEmitter() is built on such a Subject(). It is a good practise to use Subject() instead of EventEmitter() for cross-component communication.

About Author

Author Image
Satwinder Singh

Satwinder had been working as a free-lancer for past 1-year and recently joined Oodles Technologies as a UI-Developer. His skills are : Jquery , Html , Css , Bootstrap and Javascript.

Request for Proposal

Name is required

Comment is required

Sending message..