Search code examples
angularrxjs-observables

Using Angular Observable to subscribe to Session Storage key


I'm trying to accomplish what I had hoped would be a simple "look at the key in Session Storage and update it when it changes" scenario, but Observables really trip me up.

message$ = new Observable(observer => {
    observer.next(window.sessionStorage.getItem('message'));
});
    
ngOnInit() {
    this.message$.subscribe();
}

And the message$ is bound to the HTML, pretty straightforward:

<p id="message">{{message$ | async}}</p>

The Observable will output the text to the HTML if there's already value stored in 'message' but if there's no message on init and then it gets added, or the message value does exist and is updated, nothing happens. I'm obviously doing something wrong, and I would appreciate the insight of someone knowledgeable with Observables.


Solution

  • I think what you're looking for is a StorageEvent

    You can create your observable from this event using fromEvent, like this:

    const message$ = fromEvent<StorageEvent>(window, "storage").pipe(
      filter(event => event.storageArea === sessionStorage),
      filter(event => event.key === "message"),
      map(event => event.newValue)
    );
    

    Notice that I added filters to specifically look for updates of sessionStorage and I specified the key === "message", but you can also use localStorage and any key you want

    Also, as Damian C pointed out, you don't need to subscribe to this observable if you're planning to only use it in template.

    EDITED: solution above only working when you have multiple tabs opened and want to synchronize changes to storage. Check this answer

    I think you have to change a place where you set your value to sessionStorage. My suggestion is to use your own StorageService (my example) where you will set your value to storage and keep an observable, which should emit when you are setting key/value.

    I did an example on stackblitz

    https://stackblitz.com/edit/angular-3szmzd