Home > OS >  What is the best way to pass data between two components which don't have parent-child relation
What is the best way to pass data between two components which don't have parent-child relation

Time:06-02

What is the best way to pass data between two components which don't have parent-child relation in Angular 13

CodePudding user response:

1. Shared service.

Shared service

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

@Injectable({ providedIn: 'root' })
export class MessageService {
    private subject = new Subject<any>();

    sendMessage(message: string) {
        this.subject.next({ text: message });
    }

    onMessage(): Observable<any> {
        return this.subject.asObservable();
    }
}

Component A

export class ComponentA implements OnInit, OnDestroy {
    isAlive = true;

    constructor(private messageService: MessageService) { }

    ngOnInit(): void {
      this.messageService.onMessage()
          .pipe(takeWhile(() => this.isAlive)).subscribe(message => {
            // Do anything
        });
    }

    ngOnDestroy() {
        this.isAlive = false;
    }
}

Component B

export class ComponentB {
    constructor(private messageService: MessageService) { }

    sendMessage(): void {
        // send message to subscribers via observable subject
        this.messageService.sendMessage('Hello!');
    }
}

2. Ngrx store

Ngrx is bit complex and may be too much for small projects. Here is the complete documentation.

3. LocalStorage or SessionStorage

Depending on your requirement you can use these storages. But they are not like observables. Therefore, if a new value available, they don't knock. You have to manually check the storage for new values.

CodePudding user response:

Here is a little example, this example shares the value of current theme of page to any component

component1.html

<div (click)="switchTheme()"></div>

component1.ts

import { Component, OnInit } from '@angular/core';
import { SwitcherService } from 'services/switcher.service';

@Component({
  selector: 'app-component1',
  templateUrl: './component1.html',
  styleUrls: ['./component1.scss']
})
export class component1 implements OnInit {
  currentTheme: any;

  constructor(private sw: SwitcherService) { }

  ngOnInit(): void {
    this.applyCurrentLayoutSettings();
  }

  applyCurrentLayoutSettings() {
    // here is the theme
    this.sw.getCurrentThemeObservable().subscribe( (theme: any) => this.currentTheme = theme );
  }

  switchTheme() {
    const invertedTheme = this.invertTheme();
    this.sw.switchCurrentTheme(invertedTheme);
  }
  
  invertTheme() {
    return this.currentTheme == 'dark' ? 'light': 'dark';  
  }

switcher.service.ts

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

@Injectable({
  providedIn: 'root'
})

export class SwitcherService {
  private currentThemeSubject: BehaviorSubject<any>;
  private currentTheme: Observable<any>;

  constructor() { 
    if( !this.getCurrentTheme() ) { this.setCurrentTheme('dark'); }

    this.currentThemeSubject = new BehaviorSubject<any>(this.getCurrentTheme());
    this.currentTheme = this.currentThemeSubject.asObservable();

  }
  
  switchCurrentTheme(theme: string) {
    this.setCurrentTheme(theme);
    this.currentThemeSubject.next(theme);
  }

  getCurrentThemeValue() {
    return this.currentThemeSubject.value;
  }

  getCurrentThemeObservable() {
    return this.currentTheme;
  }

  getCurrentTheme() {
    return localStorage.getItem('currentTheme');
  }

  setCurrentTheme(theme: string) {
    localStorage.setItem('currentTheme', theme);
  }
}

component2.ts

import { Component, OnInit } from '@angular/core';
import { SwitcherService } from 'services/switcher.service';

@Component({
  selector: 'app-component2',
  templateUrl: './component2.html',
  styleUrls: ['./component2.scss']
})

export class component2 implements OnInit {
  currentTheme: any;
  constructor(private sw: SwitcherService) { }

  ngOnInit(): void {
    // here is the theme
     this.sw.getCurrentThemeObservable().subscribe( (theme: any) => this.currentTheme = theme );
  }
}
  • Related