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();
}
}
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:
- Parse data from local storage
- Update the entry you want to be updated
- 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:
var data = JSON.parse(userCache.get('order'))
data.lineItems[0].serviceLocation.address = *whatever*
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
How to Calculate the Sum of Table Column in Angular 2+
Scrollable Table With Fixed Headers and Fixed First Column
React Component Not Re-Rendering When State Changes
How to Compress an Image Via JavaScript in the Browser
Use Localstorage Across Subdomains
Escaping Apostrophe (Single Quote) Character in JavaScript and HTML
Onclick Table Row With Onclick Button and Bootstrap Modal Inside
Discord Bot Not Getting All Users
Alphanumeric, Dash and Underscore But No Spaces Regular Expression Check JavaScript
How to Replace All Words of Length Less Than 3 in a String With " " (Space) in JavaScript
Javascript: How to Redirect a Page After Validation
Angular Load Async Data Before Component Initialization
How to Get the Index from a Json Object With Value
Node.Js MySQL Query in a for Loop
Trying to Add Image to Pdf Using Jspdf
Datepicker Onchange Event Not Firing in Jquery