Browser Storage and BehaviorSubject: Achieving Consistent State in Angular Through Storage Decorators
Saulo Dias
Posted on June 18, 2024
Managing data persistence in Angular applications can be a hassle, especially when you need to keep your application state synchronized with local or session storage. In this post I will provide a set of property decorators that bind your storage values to BehaviorSubject
s, ensuring that your state remains consistent with the browser's storage.
After test in production, I might consider publishing a library with them, but feel free to use the code as you wish. https://github.com/saulodias/ngx-storage
Why Use These Decorators?
They simplify the process of storing and retrieving data from local and session storage. They handle the heavy lifting for you.
With them you can:
- Automatically sync your state with browser storage.
- Use
BehaviorSubject
for reactive state management. - Easily revert to a fallback state when necessary.
How It Works
LocalStorage
The LocalStorage
decorator allows you to store data in local storage effortlessly.
import { LocalStorage } from 'ngx-storage';
import { BehaviorSubject } from 'rxjs';
class TestClass {
@LocalStorage('key', 'defaultValue')
public localStorageValue!: BehaviorSubject<string | null>;
}
SessionStorage
The SessionStorage
decorator lets you store data in session storage just as easily.
import { SessionStorage } from 'ngx-storage';
import { BehaviorSubject } from 'rxjs';
class TestClass {
@SessionStorage('key', 'defaultValue')
public sessionStorageValue!: BehaviorSubject<string | null>;
}
Custom JSON Converter
For more complex types, you can provide a custom JSON converter.
import { JsonConverter, SessionStorage } from 'ngx-storage';
import { BehaviorSubject } from 'rxjs';
type CustomType = { date: Date };
type CustomTypeStored = { date: number };
const customConverter: JsonConverter<CustomType, CustomTypeStored> = {
toJson: (object) => ({ date: object.date.getTime() }),
fromJson: (object) => ({ date: new Date(object.date) }),
};
class TestClass {
@SessionStorage('key', { date: new Date() }, customConverter)
public sessionStorageValue!: BehaviorSubject<CustomType | null>;
}
Using NgxStorage in an Angular Service
Here's an example of how to use these decorators in an Angular service:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { LocalStorage, SessionStorage } from 'ngx-storage';
@Injectable({
providedIn: 'root',
})
export class StorageService {
@LocalStorage('localKey', 'defaultLocalValue')
public localStorageValue!: BehaviorSubject<string | null>;
@SessionStorage('sessionKey', 'defaultSessionValue')
public sessionStorageValue!: BehaviorSubject<string | null>;
constructor() {
// Subscribe to localStorageValue
this.localStorageValue.subscribe(value => {
console.log('LocalStorage value:', value);
});
// Set a new value to localStorageValue
this.localStorageValue.next('newLocalValue');
// Subscribe to sessionStorageValue
this.sessionStorageValue.subscribe(value => {
console.log('SessionStorage value:', value);
});
// Set a new value to sessionStorageValue
this.sessionStorageValue.next('newSessionValue');
}
}
Using the Service in a Component
import { Component, OnInit } from '@angular/core';
import { StorageService } from './storage.service';
@Component({
selector: 'app-storage-example',
templateUrl: './storage-example.component.html',
styleUrls: ['./storage-example.component.css']
})
export class StorageExampleComponent implements OnInit {
constructor(private storageService: StorageService) {}
ngOnInit() {
// Access and use the storage service properties as needed
console.log('LocalStorage Initial:', this.storageService.localStorageValue.value);
console.log('SessionStorage Initial:', this.storageService.sessionStorageValue.value);
// Update the values
this.storageService.localStorageValue.next('updatedLocalValue');
this.storageService.sessionStorageValue.next('updatedSessionValue');
}
}
Setting Fallback State
When null
is passed to .next()
, the fallback state is set instead.
this.localStorageValue.next(null); // Reverts to 'defaultLocalValue'
this.sessionStorageValue.next(null); // Reverts to 'defaultSessionValue'
Note that this is beta and not published, but you can use the code as you wish, for commercial and personal purposes. It's provided as it is though, with no guarantee.
Posted on June 18, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.