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 );
}
}