Search code examples
angularangular2-services

How can I watch for changes to localStorage in Angular2?


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


Solution

  • 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