How to Look for Changes in Localstorage in Angular 4

How can I watch for changes to localStorage in Angular2?

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

Detect local storage changes and show on page without reloading

I think you should use rxjs stream to accomplish this.

   private storageSub= new Subject<string>();
...

watchStorage(): Observable<any> {
return this.storageSub.asObservable();
}

setItem(key: string, data: any) {
localStorage.setItem(key, data);
this.storageSub.next('added');
}

removeItem(key) {
localStorage.removeItem(key);
this.storageSub.next('removed');
}

Detect variable changes into localStorage angular 8

You could move the functions to a singleton service and monitor the value using observables. Try the following

Shared service

import { BehaviorSubject, Observable } from 'rxjs';  // <-- included 'Observable' here - with capital 'O'

@Injectable()
export class SharedService {
private addUsuarioSource = new BehaviorSubject<string>('false');
public addUsuario$ = this.addUsuarioSource.asObservable();

constructor() {
this.addUsuario$.subscribe(status => window.localStorage.setItem('addUsuario', status)); // <-- changed 'userStatus' to 'status'
}

getAddUsuario(): Observable<string> { // <-- capital 'O' instead of small 'o'
let userStatus = window.localStorage.getItem('addUsuario');
userStatus = (userStatus === 'false' || userStatus == null) ? 'true' : 'false';
this.addUsuarioSource.next(userStatus);
return this.addUsuario$;
}
}

Navbar component

import { pipe } from 'rxjs';
import { map, take } from 'rxjs/operators';

export class NavbarComponent implements OnInit() {
subscription: any;

ngOnInit() {
if (this.subscription) {
this.subscription.unsubscribe();
}
this.subscription = this.sharedService.getAddUsuario().pipe(take(1)).subscribe(status => {
// this callback will be called only once due to `pipe(take(1))`
// `status` variable with value 'true' or 'false' as string
});
}
}

Another component

this.sharedService.addUsuario$.subscribe(status => {
// this callback will be called each time a new user status is pushed
// `status` variable with value 'true' or 'false' as string
})

I am using BehaviorSubject to provide a default value. You could use Rxjs Subject if you do not wish to provide a default value. Explanation for pipe(take(1)) can be found here.

Note: Storing boolean in local storage isn't a good idea. Because you can only store strings and it returns the values as strings. So you cannot do something like *ngIf==="status" or *ngIf==="!status". It would be *ngIf="status === 'true'" and *ngIf="status === 'false'".

Working example: Stackblitz

Watch for changes in LocalStorage angular2

What you want is a Subject. Check out the docs here (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)

For a quick example, something like this:
@Injectable()
export class StorageService {
...
private storageSub= new Subject<String>();
...

watchStorage(): Observable<any> {
return this.storageSub.asObservable();
}

setItem(key: string, data: any) {
localStorage.setItem(key, data);
this.storageSub.next('changed');
}

removeItem(key) {
localStorage.removeItem(key);
this.storageSub.next('changed');
}
}

Inside Component

constructor(private storageService: StorageService ){}
ngOnInit() {
this.storageService.watchStorage().subscribe((data:string) => {
// this will call whenever your localStorage data changes
// use localStorage code here and set your data here for ngFor
})

}

How to watch for localstorage changes with AngularJS

You can create a $watch function that returns anything you want. When it changes, your $watch will run.

$scope.$watch(function(){
return $localstorage.getObject('codes');
}, function(newCodes, oldCodes){
$scope.codes = newCodes;
});

Make sure to do performance testing on that. This function will be called a lot.


A better way would be to use events and only update codes when necessary.

Controller A:

var codes = updateCodesAndStoreInLocalStorage(); // <That part's up to you
$rootScope.$emit('codesUpdated', codes);

Controller B:

$rootScope.$on('codesUpdated', function(event, codes){
$scope.codes = codes; //Rely on localStorage for "storage" only, not for communication.
});

Angular update Local Storage value

When you have to update data in your local storage, you usually need to:

  1. Parse data from local storage
  2. Update the entry you want to be updated
  3. Save data in local storage

This is due to the string nature of local storage: when you save objects, arrays or whatever you want, the are converted to string since Local Storage is a string storage.

But since you're a lucky boy and you're using Angular, there's plenty of modules you can use to manage local storage without the need to worry about stringification.

My personal favourite is ngStorage

--- EDIT ---

Well, with angular-cache you simply follow the steps above:

  1. var data = JSON.parse(userCache.get('order'))
  2. data.lineItems[0].serviceLocation.address = *whatever*
  3. userCache.put('order', data)

angularjs and localStorage change event

There is an angular localStorage module:

https://github.com/grevory/angular-local-storage

var DemoCtrl = function($scope, localStorageService) {

localStorageService.clearAll();

$scope.$watch('localStorageDemo', function(value){
localStorageService.add('localStorageDemo',value);
$scope.localStorageDemoValue = localStorageService.get('localStorageDemo');
});

$scope.storageType = 'Local storage';

if (!localStorageService.isSupported()) {
$scope.storageType = 'Cookie';
}

};

After further thought you may need to change the module to broadcast on setItem so that you can get notified if the localStorage has been changed. Maybe fork and around line 50:

localStorage.setItem(prefix+key, value);
$rootScope.$broadcast('LocalStorageModule.notification.setItem',{key: prefix+key, newvalue: value}); // you could broadcast the old value if you want

or in the recent version of the library the casing was changed

$rootScope.$broadcast('LocalStorageModule.notification.setitem',{key: prefix+key, newvalue: value}); 

Then in your controller you can:

$scope.$on('LocalStorageModule.notification.setItem', function(event, parameters) {
parameters.key; // contains the key that changed
parameters.newvalue; // contains the new value
});

Here is a demo of the 2nd option:
Demo: http://beta.plnkr.co/lpAm6SZdm2oRBm4LoIi1

** Updated **

I forked that project and have included the notifications here in the event you want to use this project: https://github.com/sbosell/angular-local-storage/blob/master/localStorageModule.js

I believe the original library accepted my PR. The reason I like this library is that it has a cookie backup in case the browser doesn't support local storage.



Related Topics



Leave a reply



Submit