Pass data between component in Angular

Issue

I have this page structure

enter image description here

app.component.html

<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>

I load all data in app.component.ts file using shared service

import { Component,HostListener } from '@angular/core';
import { Router } from '@angular/router';
import { TokenService } from './shared/token.service';
import { AuthStateService } from './shared/auth-state.service';
import { SharedData,SharedService } from './shared/shared-service.service';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';



@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  baseUrl = environment.baseUrl;
  homePageTitle:any;
  title:any;
  ...
  data: SharedData;


  constructor(
    private auth: AuthStateService,
    public router: Router,
    public token: TokenService,
    private http: HttpClient, private domSanitizer: DomSanitizer,
    private sharedService: SharedService
  ) {
  }

  ngOnInit() {

    this.http.get(this.baseUrl+'api/content').subscribe(result  => {
      this.title=result['response'].title;
      ... 
      ...
     this.setData();
    });
    
  }

  setData(): void {
 this.sharedService.setData({title: this.title,....});
      this.sharedService.sharedData.subscribe(result => this.data = result);
  }
}

shared-service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
import { BehaviorSubject } from 'rxjs';

export interface SharedData {
  title: any;
  ...

}

@Injectable({
  providedIn: 'root'
})

export class SharedService  {

  private sharedData$ = new BehaviorSubject<SharedData>({title: '',...other fields});
  sharedData = this.sharedData$.asObservable();

  baseUrl = environment.baseUrl;
  constructor(private http: HttpClient) { }

  setData(data: SharedData): void {
    this.sharedData$.next(data);
  }
}

when i subscribe to this service in footer,header and home component i get blank data in all the fields.

this.sharedService.sharedData.subscribe(result => this.data = result);

enter image description here

Solution

The 0xBobby’s answer works fine with parent-child components but in more complex scenarios (with routing, for example) I would recommend using a shared service and BehaviorSubject for communication between components. Chech this Stackblitz example based loosely on your code: https://stackblitz.com/edit/angular-jbus9x?file=src/app/app.component.ts.

First, you create a SharedService used to, well, share data between components:

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

  private sharedData$ = new BehaviorSubject<SharedData>({title: '', logo: ''});
  sharedData = this.sharedData$.asObservable();

  constructor() { }

  setData(data: SharedData): void {
    this.sharedData$.next(data);
  }

The in the HomeComponent you set the data you want to share:

  constructor(private sharedService: SharedService) {}

  setData(): void {
    this.sharedService.setData({title: this.title, logo: this.logo});
  }

  ngOnInit(): void {
    this.http.get(this.baseUrl+'api/content').subscribe(result  => {
        this.title=result.title;
        this.logo=result.logo;
        this.setData();
    });
  }

and finally you subscribe to the the observable in AppComponent and FooterComponent where you want to show the same data:

export class AppComponent  {
  
  data: SharedData;

  constructor(private sharedService: SharedService) {}

  ngOnInit(): void {
    this.sharedService.sharedData.subscribe(result => this.data = result);
  }
  
}

The advantage of this solution is that the communication works between deeply nested components, with routed componentes, with services, etc.

Answered By – Kari F.

Answer Checked By – Gilberto Lyons (AngularFixing Admin)

Leave a Reply

Your email address will not be published.