user11185486
user11185486

Reputation:

Angular Tell other components that there has been a change without using intervals

I currently have something like this in the footer component of my project

ngOnInit() {

    const checkLocalStorage = interval(15000);
        checkLocalStorage.subscribe(data => {
        // code for checking the Localstorage
    });

}

I don't like the idea of having timers looping to check for changes every so many seconds.

I need a simple, clean way to communicate messages to other components (non related component).

I know about RxStore is complicated.

I there a simple way to send a simple message to another component telling it to run a method in it's component?

How can I do this without using interval or other loop?

Upvotes: 0

Views: 38

Answers (3)

taras-d
taras-d

Reputation: 1827

Simplest way is to use HTML CustomEvents

Listen to event:

document.addEventListener('my-event', () => {
  console.log('My event !');
});

Dispatch event:

document.dispatchEvent( new CustomEvent('my-event') );

Upvotes: 0

Shriniwas b
Shriniwas b

Reputation: 336

Use this event services, to communicate between components.

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

const ServiceName: string = "Events Service";

@Injectable()
export class EventsService implements IEventsService {
    private events = { };

    constructor() { }

    public subscribe(event: string): Observable<any>;
    public subscribe(event: string, callback: (value: any) => void): Subscription;  
    public subscribe(event: string, callback: (value: any) => void, error: (error: any) => void): Subscription;
    public subscribe(event: string, callback: (value: any) => void, error: (error: any) => void, complete: () => void): Subscription;
    public subscribe(event: string, callback?: (value: any) => void, error?: (error: any) => void, complete?: () => void) {
        if (!event) {
            throw new Error(`[${ServiceName}] => Subscription method must get event name.`);
        }

        if (this.events[event] === undefined) {
            this.events[event] = new Subject<any>();
        }

        if (typeof callback !== 'function') {
            return this.events[event].asObservable();
        } else {
            return this.events[event].asObservable().subscribe(callback, error, complete);
        }
    }

    public publish(event: string, eventObject?: any) {
        if (!event) {
            throw new Error(`[${ServiceName}] => Publish method must get event name.`);
        } else if (!this.events[event]) {
            return;
        }

        this.events[event].next(eventObject);
    }
}

export interface IEventsService {
    publish(event: string, eventObject?: any);
    subscribe(event: string): Observable<any>;
    subscribe(event: string, callback: (value: any) => void): Subscription;
    subscribe(event: string, callback: (value: any) => void, error: (error: any) => void): Subscription;
    subscribe(event: string, callback: (value: any) => void, error: (error: any) => void, complete: () => void): Subscription;
}

interface ISubscribe{
    (event: string): Observable<any>;
    (event: string, callback: (value: any) => void): Subscription;
    (event: string, callback: (value: any) => void, error: (error: any) => void): Subscription;
    (event: string, callback: (value: any) => void, error: (error: any) => void, complete: () => void): Subscription;
}

How to use this service :

publish event from XYZ component

   publishNewEvent(){
     this.eventsService.publish("PROFILE_UPDATED");
   }

subscribe to an event in ABC component

constructor(private eventsService: EventsService){
   this.eventsService.subscribe("PROFILE_UPDATED", () => {
      console.log("Called");
   });
}

Upvotes: 1

tommueller
tommueller

Reputation: 2496

That is what Angular's Component Interaction is made for. Using @Input to pass data into a component and @Output to notify a parent about a childs event.

If you have an app structure that makes this too complicated, you would want to think about using Redux.

If that is too complicated or over-engineered for this you can write a simple service. This service should provide an Observable which your footer component subscribes to. From the other component now run a function in the service which delivers the next value in the Observable.

Upvotes: 1

Related Questions