How can I watch for changes to localStorage in Angular2?

Morgan G picture Morgan G · Feb 14, 2016 · Viewed 33.6k times · Source

I was trying to figure out how to get a menu to appear and disappear based on being logged in in a previous post. But I think a better and possibly easier question would be, how can I watch for changes to localstorage?

I am using json web tokens in local storage for my authentication, I would love to watch for a change to localStorage and then re-update my view on new information.

I set my localStorage with this

localStorage.setItem('jwt', my_token);

The things I would like to do is check if I have a token, if I don't nothing happens, but when there is a change fire an event. I would especially like it if I could only watch for a certain named event like localStorage.getItem('jwt').

Thanks!

EDIT:

Gunter pointed me in the right direction but just in case anyone is still fairly confused by that, here is a plunker showing you how to do it. http://plnkr.co/edit/TiUasGdutCsll1nI6USC?p=preview

Answer

Stephen picture Stephen · Dec 6, 2017

The key thing is to use window.addEventListener("storage", . While the library probably does it the "right" way for angular, here is a "light" version I put together, using .bind(this) instead of mucking about in angular's internals.

    import { Injectable, OnDestroy } from '@angular/core';
    import { Subject } from 'rxjs/Subject';
    import { share } from 'rxjs/operators';
    
    @Injectable()
    export class StorageService implements OnDestroy {
      private onSubject = new Subject<{ key: string, value: any }>();
      public changes = this.onSubject.asObservable().pipe(share());
    
      constructor() {
        this.start();
      }
    
      ngOnDestroy() {
        this.stop();
      }
    
      public getStorage() {
        let s = [];
        for (let i = 0; i < localStorage.length; i++) {
          s.push({
            key: localStorage.key(i),
            value: JSON.parse(localStorage.getItem(localStorage.key(i)))
          });
        }
        return s;
      }
    
      public store(key: string, data: any): void {
        localStorage.setItem(key, JSON.stringify(data));
        this.onSubject.next({ key: key, value: data})
      }
    
      public clear(key) {
        localStorage.removeItem(key);
        this.onSubject.next({ key: key, value: null });
      }
    
    
      private start(): void {
        window.addEventListener("storage", this.storageEventListener.bind(this));
      }
    
      private storageEventListener(event: StorageEvent) {
        if (event.storageArea == localStorage) {
          let v;
          try { v = JSON.parse(event.newValue); }
          catch (e) { v = event.newValue; }
          this.onSubject.next({ key: event.key, value: v });
        }
      }
    
      private stop(): void {
        window.removeEventListener("storage", this.storageEventListener.bind(this));
        this.onSubject.complete();
      }
    }

LocalStorageTwoTabs