Angular Services For Sharing Data Between Components

I hope you have read all my previous tutorials. My previous article was about Sharing Data Between Component Using Angular V4 And Above, in which I explained the methods by which we can share data between the components parent-child. Today, I am here with one more article which is very important for Angular developers.

As I already told you, it’s a basic need for any application to send and play with data. It should be able to perform operations which are necessary according to our requirement as we have used @Input and @Output. Here, we need to understand why we are using services for sharing the data while we have @Input and @Output. Well, the answer is we are using  the @Input and @output for sharing the data between parent and child. Suppose we have the requirement to share the data between components where each component is separate. This time, the Angular service comes into the picture.

One thing  that's very necessary to know is that we are not using Angular Services only for sharing the data between components. The basic need of Angular service is to communicate to the API with the help of HTTP verb and perform the required operation as GET , POST the data etc.

Now, the first thing that comes to your mind is what Angular service is and why we use it.

What is Angular Service?

An Angular service is simply a function that allows you to access its properties and methods. For example, if we have any code which gets the data we will use it in one component and now if you want to use the same code in another component to get the same data , we will not add the same code again and again. We will simply create a service and it will be used by the component where we want the data.

Why do we use Angular Services?

Services are commonly used for storing data and making HTTP calls for retrieving, posting, updating and deleting the data we need in our application.

Now I am going to explain how we will share the data by service from one component to another while these are not in a parent child relationship.

First,  I have created one service, either command as ng service <srvicename>,  or created a file option within the Angular application where we are creating the application.  In my application I have created the service data.service.ts as,

  1. import { Injectable } from '@angular/core';  
  2.   
  3. @Injectable()  
  4. export class DataService {  
  5.   
  6.   private data = {};  
  7.   
  8.  setOption(option, value) {      
  9.     this.data[option] = value;  
  10.   }  
  11.   
  12.   getOption() {  
  13.     return this.data;  
  14.   }  
  15. }  

As you can see above, I have created two methods,  setOption and GetOption, in the service for  getting and setting the required value from our component.

Now, I have created two components,

app.first.component.ts

For setting the value using setOption method by service within the first component,

  1. export class FirstComponent {  
  2.     public size: number;  
  3.     public square: number;  
  4.   
  5.     constructor(_dataService: DataService) {  
  6.         this.size = 16;  
  7.         this.square = Math.sqrt(this.size);  
  8.   
  9.         _dataService.setOption('size'this.size);  
  10.         _dataService.setOption('square'this.square);  
  11.     }  
  12. }  

app.second.component.ts

For getting the added value using getOption method by service within the second component,

  1. export class SecondComponent {  
  2.   public data;  
  3.     
  4.   constructor(_dataService: DataService) {  
  5.     debugger;  
  6.     this.data = _dataService.getOption();  
  7.   }  
  8. }  

As you know we are reading about sharing data between two components while each component is separate using service, so the important thing is, how we will show the value has changed?  For this purpose,  I have added an anchor within the first component and with the help of [routerLink] we will show the another component using routing. Now one thing you may be wondering: What is routing?

What is Routing?

Angular provides a Router to make it easier to define routes for the web applications and to navigate from one view to another view so we are using routing only for moving one page or view to another view. I have added routing in this application so that we can move the first component to second component and get the added value using setOption method from the first component as:

app.routing.ts

  1. import { ModuleWithProviders } from '@angular/core';  
  2. import { Routes, RouterModule } from '@angular/router';  
  3. import { FirstComponent } from './app.first.component';  
  4. import { SecondComponent } from './app.second.component';  
  5.   
  6. const appRoutes: Routes = [  
  7.     { path: '', component: FirstComponent },  
  8.     { path: 'second', component: SecondComponent },  
  9.   
  10. ];  
  11.   
  12. export const routing: ModuleWithProviders =  
  13.     RouterModule.forRoot(appRoutes);  

As you can see above we have added Routes and RouterModule which is mainly for routing .

Also, I have added Routes array with path and component. The path denotes the url and component denotes the component name which means corresponding component html page will run and show the view which we have added within template or templateurl of @component decorator.

One thing which is very important that we have to add is   <router-outlet></router-outlet> within  the main component file as I have added with app.component.html page which is my main component, like this:

app.component.html

  1. <router-outlet></router-outlet>  

The router-outlet is mainly showing the view, which  means component html page which we have added in the routing .

Now, the most important thing which we have to do is we have to register all the above components, service and routing files in the app.module.ts file as I have explained in my previous tutorial:

app.module.ts

  1. import { AppComponent } from './app.component';  
  2. import { FirstComponent } from './app.first.component';  
  3. import { SecondComponent } from './app.second.component';  
  4. import { DataService } from './data.service'  
  5. import { routing } from './app.routing';  
  6.   
  7. @NgModule({  
  8.   declarations: [  
  9.     AppComponent, FirstComponent, SecondComponent,  
  10.   ],  
  11.   imports: [  
  12.     BrowserModule, routing  
  13.   ],  
  14.   providers: [DataService],  
  15.   bootstrap: [AppComponent]  
  16. })  
  17. export class AppModule { }  

As you can see above, I have added both the components in the declaration section and routing within the imports section where all the modules will be registered .

The service which we have created we will add within the providers:[] section as I have added DataService in the above example.

Now, if everything is completed above, you can run the application using two steps :

Step 1

Open the node js command window and move to the location where you have added the application .

Step 2 - execute the command ng serve

When application runs successfully you should see the below output:

Angular

You can see above, the data shows what we have added with the first component and assigns the value within constructor as,

  1. public size: number;  
  2.     public square: number;  
  3.   
  4.     constructor(_dataService: DataService) {  
  5.         this.size = 16;  
  6.         this.square = Math.sqrt(this.size);  
  7.   
  8.         _dataService.setOption('size'this.size);  
  9.         _dataService.setOption('square'this.square);  
  10.     }  

Service Method

  1. private data = {};  
  2.   
  3.   setOption(option, value) {  
  4.     debugger;  
  5.     this.data[option] = value;  
  6.   }  

Now, I am using setOption method within constructor which is the service method. Here setOption method sets the above size and square value in the service data object.

I have added an anchor also for navigating from the first component to the second component so when we click on the above and go to the second component link it will navigate to the second component and in the second component I am using getOption service method for getting the data value in the second component within the constructor as:

  1. public data;    
  2.   constructor(_dataService: DataService) {  
  3.     debugger;  
  4.     this.data = _dataService.getOption();  
  5.   }  

Service Method

  1. getOption() {  
  2.     return this.data;  
  3.   }  

Now when we click on anchor link and go to the second component it should show the below output,

Angular

So you can see the first component values are shared with the second component using service.

The entire application code is:

  • data.service.ts
    1. import { Injectable } from '@angular/core';  
    2.   
    3. @Injectable()  
    4. export class DataService {  
    5.   
    6.   private data = {};  
    7.   
    8.   setOption(option, value) {  
    9.     debugger;  
    10.     this.data[option] = value;  
    11.   }  
    12.   
    13.   getOption() {  
    14.     return this.data;  
    15.   }  
    16. }  
  • app.component.ts
    1. import { Component, OnInit } from '@angular/core';  
    2. import { DataService } from "./data.service";  
    3.   
    4. @Component({  
    5.   selector: 'app-root',  
    6.   templateUrl: 'app.component.html',  
    7.     
    8. })  
    9. export class AppComponent {  
    10.   public title: string = 'Sharing data using service';  
    11.   
    12.   constructor() {  
    13.   
    14.   }  
    15. }  
  • app.component.html
    1. <div style="text-align:center">  
    2.   <h1>  
    3.     {{title}}  
    4.   </h1>  
    5.   <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">  
    6.   
    7.   <router-outlet></router-outlet>  
  • app.first.component.ts
    1. import { Component, OnInit } from '@angular/core';  
    2. import { DataService } from "./data.service";  
    3.   
    4. @Component({  
    5.     selector: 'app-root',  
    6.    templateUrl: 'app.first.component.html',   
    7. })  
    8. export class FirstComponent {  
    9.     public size: number;  
    10.     public square: number;  
    11.   
    12.     constructor(_dataService: DataService) {  
    13.         this.size = 16;  
    14.         this.square = Math.sqrt(this.size);  
    15.         _dataService.setOption('size'this.size);  
    16.         _dataService.setOption('square'this.square);  
    17.     }  
    18. }  
  • app.first.component.html
    1. <hr>  
    2. <h1 style="color:#253535">First Component</h1>  
    3. <div style="text-align:center">  
    4.     <div>  
    5.         <table>  
    6.             <tr>  
    7.                 <td>  
    8.                     Size is :  
    9.                 </td>  
    10.                 <td>  
    11.                     {{ size }}  
    12.                 </td>  
    13.             </tr>  
    14.             <tr>  
    15.                 <td>  
    16.                     Square is:  
    17.                 </td>  
    18.                 <td>  
    19.                     {{square}}  
    20.                 </td>  
    21.             </tr>  
    22.             <tr>  
    23.                 <td>  
    24.   
    25.                 </td>  
    26.                 <td>  
    27.                     <a [routerLink]="['second']">go to second component</a>  
    28.                 </td>  
    29.             </tr>  
    30.         </table>  
    31.     </div>  
    32.     <hr>  
  • app.second.component.ts
    1. import { Component, OnInit } from '@angular/core';  
    2. import { DataService } from "./data.service";  
    3.   
    4. @Component({  
    5.   selector: 'grid',  
    6.   templateUrl: 'app.second.component.html',  
    7.     
    8. })  
    9. export class SecondComponent {  
    10.   public data;  
    11.     
    12.   constructor(_dataService: DataService) {  
    13.     debugger;  
    14.     this.data = _dataService.getOption();  
    15.   }  
    16. }  
  • app.second.component.html
    1. <hr>  
    2. <h1 style="color:brown">Second Component</h1>  
    3.   
    4. <div style="text-align: left">  
    5.     <table>  
    6.         <tr>  
    7.             <td>  
    8.                 Size is :  
    9.             </td>  
    10.             <td>  
    11.                 {{ data.size }}  
    12.             </td>  
    13.         </tr>  
    14.         <tr>  
    15.             <td>  
    16.                 Square is:  
    17.             </td>  
    18.             <td>  
    19.                 {{data.square}}  
    20.             </td>  
    21.         </tr>  
    22.          
    23.     </table>  
    24. </div>  
    25. <hr>  
  • app.routing.ts
    1. import { ModuleWithProviders } from '@angular/core';  
    2. import { Routes, RouterModule } from '@angular/router';  
    3. import { FirstComponent } from './app.first.component';  
    4. import { SecondComponent } from './app.second.component';  
    5.   
    6. const appRoutes: Routes = [  
    7.     { path: '', component: FirstComponent },  
    8.     { path: 'second', component: SecondComponent },  
    9. ];  
    10.   
    11. export const routing: ModuleWithProviders =  
    12.     RouterModule.forRoot(appRoutes);  
  • app.module.ts
    1. import { BrowserModule } from '@angular/platform-browser';  
    2. import { NgModule } from '@angular/core';  
    3. import { AppComponent } from './app.component';  
    4. import { FirstComponent } from './app.first.component';  
    5. import { SecondComponent } from './app.second.component';  
    6. import { DataService } from './data.service'  
    7. import { routing } from './app.routing';  
    8. @NgModule({  
    9.   declarations: [  
    10.     AppComponent, FirstComponent, SecondComponent,  
    11.   ],  
    12.   imports: [  
    13.     BrowserModule, routing  
    14.   ],  
    15.   providers: [DataService],  
    16.   bootstrap: [AppComponent]  
    17. })  
    18. export class AppModule { }  
  • style.css
    1. /* You can add global styles to this file, and also import other style files */  
    2. table, th , td {  
    3.   border: 1px solid grey;  
    4.   border-collapse: collapse;  
    5.   padding: 5px;  
    6.   font-size: 22px;  
    7. }  
    8. table tr:nth-child(odd) {  
    9.   background-color: #ADE9CB;  
    10. }  
    11. table tr:nth-child(even) {  
    12.   background-color: #E2AAAA;  
    13.  

So, these are the above files which I am using with the application. You can also download the application by zip file which I have shared with this article.

Conclusion

As we know, sharing data within the component while components are separate is  a very important concept in Angular and most of the time we need it  as per our requirement. I hope you liked this -- please share it if you did.