Angular Sharing Data between Two Different Components Using RxJs Subjects (Learn It In 21 Steps)
Hey Everyone !!!, Thanks for visiting my medium I hope you doing well. Please find the below steps to implement the sharing data between two components using Subjects in the angular application
0. Before starting the application, you need to know about subjects in angular. Subject concepts will be available in the RxJs library.
Here Subject is the same as the observable. Once declared subject in any of the service files or component files. We can invoke it wherever it is required in the logic to achieve our expectations.
In subjects, the next function will be there you can call the subject by using the “next” method. For getting data from the subject, you need to use “subscribe” in that way you will get the data from a subject as a value (Always will get the value from the subject).
Please find the types of subjects below
I think you understood something, In the below example am using the subject to pass the data from one component to another component. For achieving this am using Behavior Subject. For more information, please visit the RxJs website
- Create an angular project with the below command.
ng new angular-app-sharing-data-using-subjects
2. After successful creation of the angular app, change the file directory to project-name. by using the below command
cd angular-app-sharing-data-using-subjects
3. Open the project in vs code using “code .” or open with “vs code” after that run the project by using the “ng serve” command and open the project in the browser using localhost:4200
4. Open the app component in vs code and remove the content created by angular CLI while developing the app.
5. Generate components of the user’s list, and user details components under the components folder, and also create user service under the apis folder by using the below commands.
ng generate component users-list
ng generate component user-details
ng generate service user
6. Install the bootstrap library by using the below command and also import the URL inside styles.scss file to load the bootstrap styles inside the application. If you had done already, please ignore this step.
npm install bootstrap
- Import the bootstrap in styles.scss file as below
@import ‘../node_modules/bootstrap/dist/css/bootstrap.min.css’;
7. After successfully creating the above files. Open app.module.ts, import HttpClientModule, and add it to the imports array like below.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { UserDetailsComponent } from './components/user-details/user-details.component';
import { UsersListComponent } from './components/users-list/users-list.component';
import { UsersService } from './apis/users.service';
import { HttpClientModule } from '@angular/common/http';@NgModule({
declarations: [
AppComponent,
UserDetailsComponent,
UsersListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [UsersService],
bootstrap: [AppComponent]
})
export class AppModule { }
8. After that open “users.service.ts” and import “HttpClient”, and also add it as a dependency inside the constructor.
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';@Injectable({
providedIn: 'root'
})
export class UsersService {public uri ='https://letstalk-be.herokuapp.com'private headers:HttpHeaders= new HttpHeaders({
'Content-Type':'application/json',
'Accept':"application/json",
'Access-Control-Allow-Methods':'GET,POST,PUT,DELETE',
'Authorization':''
});
constructor(private http:HttpClient) { }
}
9. After that Add two service methods, loadUsers and loadUsersById to call the user’s endpoint.
- Here loadUsers() is to loads all the users from the service.
- Here loadUsersById(id) is to load single user by user-id.
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';@Injectable({
providedIn: 'root'
})
export class UsersService {public uri ='https://letstalk-be.herokuapp.com'private headers:HttpHeaders= new HttpHeaders({
'Content-Type':'application/json',
'Accept':"application/json",
'Access-Control-Allow-Methods':'GET,POST,PUT,DELETE',
'Authorization':''
});
constructor(private http:HttpClient) { }public loadUsers(){
return this.http.get(`${this.uri}/public/users`,{headers :this.headers})
}public loadUsersById(id){
return this.http.get(`${this.uri}/public/users/${id}`,{headers :this.headers})
}
}
10***. Create BeheviourSubject inside the service file and pass an initial value as null.
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';@Injectable({
providedIn: 'root'
})
export class UsersService {public uri ='https://letstalk-be.herokuapp.com'private headers:HttpHeaders= new HttpHeaders({
'Content-Type':'application/json',
'Accept':"application/json",
'Access-Control-Allow-Methods':'GET,POST,PUT,DELETE',
'Authorization':''
});public subject = new BehaviorSubject(null);
constructor(private http:HttpClient) { }public loadUsers(){
return this.http.get(`${this.uri}/public/users`,{headers :this.headers})
}public loadUsersById(id){
return this.http.get(`${this.uri}/public/users/${id}`,{headers :this.headers})
}
}
11. Finally, we have completed the service level part, after that we need to go for the view part (view logic).
Open the “app.component.html” file in vs code by using Ctrl + P and add the users-list selector and user-details selector below way.
<div class="container mt-3 border p-3">
<div class="row mt-3">
<div class="col-md-4 mt-3">
<app-users-list></app-users-list>
</div>
<div class="col-md-6 m-2">
<app-user-details></app-user-details>
</div>
</div>
</div>
12. Open “users-list.component.ts”, import the user service and add it as a dependency inside the constructor.
import { Component, OnInit} from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-users-list',
templateUrl: './users-list.component.html',
styleUrls: ['./users-list.component.scss']
})
export class UsersListComponent implements OnInit {constructor(private api: UsersService) { }public ngOnInit(): void {
}
}
13. After that add usersData, and selectedUserId variables to store the user’s data and selected user values.
Here, variable usersData stores users' data, and variable selectedUserId to store the selected user data to highlight the li element inside users-list.component.html.
import { Component, OnInit} from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-users-list',
templateUrl: './users-list.component.html',
styleUrls: ['./users-list.component.scss']
})
export class UsersListComponent implements OnInit {public usersData:any;
public selectedUserId="-1";constructor(private api: UsersService) { }public ngOnInit(): void {}
}
14. After that add the “loadUsers” method to call the service method to get the data and store the user’s data inside the “usersData” variable. Also, call the loadUsers method from ngOnInit().
import { Component, OnInit} from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-users-list',
templateUrl: './users-list.component.html',
styleUrls: ['./users-list.component.scss']
})
export class UsersListComponent implements OnInit {public usersData:any;
public selectedUserId="-1";constructor(private api: UsersService) { }public ngOnInit(): void {
this.loadUsers();
}public async loadUsers(){
const res = await this.api.loadUsers().toPromise().then((res:any) => res.users);
this.usersData = res;
}
}
15. Create a selectedUser method to call the loadUserById service method to get the selected user details from the service and also invoke the subject by using the “next” method to send the data from the users-list component to the user-details component in the below way.
import { Component, OnInit} from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-users-list',
templateUrl: './users-list.component.html',
styleUrls: ['./users-list.component.scss']
})
export class UsersListComponent implements OnInit {public usersData:any;
public selectedUserId="-1";constructor(private api: UsersService) { }public ngOnInit(): void {
this.loadUsers();
}public async loadUsers(){
const res = await this.api.loadUsers().toPromise().then((res:any) => res.users);
this.usersData = res;
}public async selectedUser(user){
this.selectedUserId = user?._id;
const res = await this.api.loadUsersById(this.selectedUserId).toPromise().then((res:any) => res.user);
this.api.subject.next(res);
}
}
16. Oops !!!, Not added HTML inside the users.component.html. Add the below HTML to see the changes inside the Browser UI.
<div *ngIf="usersData">
<h3 class="mb-3">List of Users</h3>
<ul class="list-group" style="min-height: 400px;overflow-y: auto;height: 400px;">
<li
class="list-group-item"
*ngFor="let user of usersData"
[ngClass]="{'active': selectedUserId === user._id}"
(click)="selectedUser(user)"
>
{{user.firstName}} {{user.secondName}} <strong>(@{{user.userName}})</strong>
</li>
</ul>
</div>
17. Up to here, we have completed the one-component view (users-list component), and the users-details component is only pending (need to call the subject by using subscribe to get the value from the subject). If you did anything wrong, please go through all the above steps.
18. Open users-details.component.ts, import the user service, and add it as a dependency inside the constructor.
import { Component, Input, OnInit } from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-user-details',
templateUrl: './user-details.component.html',
styleUrls: ['./user-details.component.scss']
})
export class UserDetailsComponent implements OnInit {
constructor (private api: UsersService) {} public ngOnInit(): void {}
}
19. After that, create a usersDetails variable to store the user details and call the subject which is declared inside the service by using subscribe event. So that you will get the value from the subject and store that value inside the userDetails variable.
import { Component, OnInit } from '@angular/core';
import { UsersService } from 'src/app/apis/users.service';@Component({
selector: 'app-user-details',
templateUrl: './user-details.component.html',
styleUrls: ['./user-details.component.scss']
})
export class UserDetailsComponent implements OnInit {
public usersDetails:any;constructor(private api: UsersService) { }public ngOnInit(): void {
this.api.subject.subscribe((value)=>{
this.usersDetails=value;
})
}
}
Here, the thing is whenever you select the user then the subject will invoke automatically.
20. After that add the Html code to display selected user-details inside browser ui.
<div *ngIf="usersDetails" class="mt-3">
<h1>Hi {{usersDetails.firstName | titlecase}} {{usersDetails.secondName | titlecase}}</h1>
<p>Username : @{{usersDetails.userName}}</p>
<p>Mobile : {{usersDetails.mobile}}</p>
<p>DOB : {{usersDetails.dob}}</p>
<p>Email Address : {{usersDetails.email}}</p>
<p>Email Verified : {{usersDetails.email_Verified ? "Yes" : "No"}}</p>
<p>Account Enabled : {{usersDetails.activated ? "Yes" : "No"}}</p>
<p>Gender : {{usersDetails.gender}}</p>
<p>Updated At: {{usersDetails.updatedAt | date:'medium'}}</p>
<p>Created At: {{usersDetails.createdAt | date:'medium'}}</p>
</div>
<div *ngIf="!usersDetails">
<h5 style="color: red;">OOPS!!! User Not Selected, Please Select Any User</h5>
</div>
21. After everything is done, do “npm install” and “ng serve” to see changes open the project by using localhost:4200. If you did anything wrong please check properly from step 1.
Output:
SOURCE CODE:
Front End:
GitHub: https://github.com/mryenagandula/angular-app-sharing-data-using-subjects
Back End:
GitHub: https://github.com/mryenagandula/Letstalk-Backend
Live Backend URI: https://letstalk-be.herokuapp.com/
Stack blitz Project Preview:
https://stackblitz.com/edit/angular-app-sharing-data-using-subjects?file=README.md
T hanks for reading my article, Please share your feedback, claps, and comments. In that way, it will be helped me to improve my articles in the future.
Please do share my story with your near and dear, Also follow and subscribe to the medium.