Angular Storage
Decorators and services for cookies, session- and localStorage
This library adds decorators that make it super easy to automagically save and restore variables using HTML5's localStorage
and sessionStorage
. It also provides Angular-Injectable Session- and LocalStorageService.
What's included?
- Decorator functions that are pretty easy to use and configure (see Decorators config):
@LocalStorage()
- to save variable in HTML5 localStorage
@SessionStorage()
- to save variable in HTML5 sessionStorage
@CookieStorage()
- to save variable as a cookie
@SharedStorage()
- to keep variable in temporary memory that can be shared across classes
@TempStorage()
- alias for SharedStorage
- Injectable
LocalStorageService
, SessionStorageService
, CookiesStorageService
and SharedStorageService
(read more here)
- Possibility of listening to storage changes
- Easy configuration (see #configuration section)
- Compatibility with:
- all previous versions
- Angular AoT compiler
angular2-localstorage
(seamless migration)
- nativescript-localstorage
- Angular since version 2
- your own project!
- Tests coverage
CHANGELOG
v3.1.0:
- added
migrateKey
decorator config option
v3.0.0:
- support for Angular 11 & TypeScript 4
- resolved circular dependencies
- added schematics
- added
.forRoot()
and .forChild()
methods for future use
- required dependencies moved to schematics installation script
v2.1.0 - support for Angular 7 & TypeScript 3
v2.0.0 - support for Angular 6 (RxJS v6)
v1.4.x:
- standardized behavior for:
- more than 1 decorator, e.g. in
@LocalStorage() @CookieStorage() variable: any;
CookieStorage
(decorator closer to variable) has higher priority, hence the value will be read from cookies only. The cookie value will be saved in localStorage
regardless of its content to keep consistency.
WebStorageService.clear('all')
- now will remove everything except ngx-store
's config (stored in localStorage
)
- removed deprecated (since v0.5)
WEBSTORAGE_CONFIG
@SharedStorage
has now alias @TempStorage
- introduced builder pattern
- added unit tests coverage
- fixes for storage events
Upcoming (TODO)
Installation
Versions 3+
Just run: ng add ngx-store
. Done!
Older versions
Configuration
Things you should take into consideration while configuring this module:
- Decorated objects have added
.save()
method to easily force save of made changes (configurable by mutateObjects
)
- Support for all
Array
methods that change array object's value can be disabled (configurable by mutateObjects
)
- Object mutation can be troublesome for object comparisons, so you can configure this feature for single field passing decorator config
- You may not use prefix (by setting it to
''
), however we recommend to use it, as it helps avoid conflicts with other libraries (configurable by prefix
)
- There are 3 ways to clear ngx-stored data:
'all'
- completely clears current Storage
'prefix'
- removes all variables prefixed by ngx-store
'decorators'
- removes only variables created by decorating functions (useful when not using prefix)
Default behaviour is specified by setting clearType
, but it's possible to pass this parameter directly into service clear()
method.
- Examples for
cookiesScope
can be found in this comment
As this project uses decorating functions, it is important to provide custom configuration in global variable named NGXSTORE_CONFIG
before Angular application load. Here are some ways to do it:
- Add
<script>
in index.html
(before Angular sources)
<script>
var NGXSTORE_CONFIG = {
prefix: 'ngx_',
clearType: 'prefix',
mutateObjects: true,
debugMode: false,
cookiesScope: '',
cookiesCheckInterval: 0,
previousPrefix: 'angular2ws_',
};
</script>
- If you use webpack, you can provide global variable in your
webpack.js
file this way:
plugins: [
new webpack.DefinePlugin({
NGXSTORE_CONFIG: JSON.stringify({
prefix: '',
})
}),
]
Decorators config
Decorating functions can take config object with the following fields:
key: string
- key under the variable will be stored, default key is the variable name
mutate: boolean
- enable or disable object mutation for instance, default depends on global config
expires: Date
- for @CookieStorage()
only, specifies expiration date, null = lifetime cookie
migrateKey: string
- previously used key from which the value will be transferred to the current key
, the old key will be cleared afterwards
Usage
-
Pretty easy to use decorators. Here is where the real magic happens.
import { CookieStorage, LocalStorage, SessionStorage } from 'ngx-store';
export class MySuperComponent {
@LocalStorage() viewCounts: number = 0;
@LocalStorage('differentLocalStorageKey') userName: string = '';
@SessionStorage({key: 'itWillBeRemovedAfterBrowserClose'}) previousUserNames: Array<string> = [];
@LocalStorage() @CookieStorage({prefix: '', key: 'user_id'}) userId: string = '';
@CookieStorage({key: 'user_workspaces', expires: new Date(new Date().getTime() + 24 * 60 * 60 * 1000)}) userWorkspaces = [];
@LocalStorage({key: 'myLocation', migrateKey: 'location'}) myLocation: string = '';
constructor() {
this.viewCounts++;
this.userName = 'some name stored in localstorage';
this.previousUserNames.push(this.userName);
for (let userName of this.previousUserNames) {
console.log(userName);
}
this.previousUserNames.map(userName => userName.split('').reverse().join(''));
}
}
Sharing variables across classes: Decorated variables can be easily shared across different classes, e.g. Angular Components (also after their destruction) without need to create new service for this purpose.
import { LocalStorage, SharedStorage } from 'ngx-store';
export class HomeComponent {
@SharedStorage() title: string = 'Homepage';
@LocalStorage() userNote: string = 'Leave your note here';
constructor() {
setTimeout(() => {
console.log('userNote:', this.userNote);
}, 5000);
}
}
export class NestedComponent {
@SharedStorage('title') homeTitle: string = '';
@LocalStorage() protected userNote: string = '';
constructor() {
console.log('homeTitle:', this.homeTitle);
console.log('userNote:', this.userNote);
this.userNote = "You've visited NestedComponent!";
}
}
Force save changes: If you need to modify stored object by not a direct assignment, then you can take advantage of .save()
method to force save made changes. Example:
import { CookieStorage, LocalStorage, SessionStorage, WebstorableArray } from 'ngx-store';
export class MySuperComponent {
@LocalStorage() someObject: any = { c: 3 };
@SessionStorage() arrayOfSomethings: WebstorableArray<number> = <any>[0,1,2,3,4];
@CookieStorage({ mutate: false }) someCookie: {version?: number, content?: string} = {};
constructor() {
this.someObject.a = 1;
this.someObject['b'] = 2;
delete this.someObject['c'];
for (let i = 0; i < this.arrayOfSomethings.length; i++) {
this.arrayOfSomethings[i] += i;
}
this.someCookie.version++;
this.someCookie.content = 'please save me';
this.someObject.save();
this.arrayOfSomethings.save();
this.someCookie = this.someCookie;
}
}
Limited lifecycle classes in AoT compilation: There is a special case when Service or Component in your application containing decorated variable is being destroyed:
import { OnDestroy } from '@angular/core';
import { LocalStorage } from 'ngx-store';
export class SomeService implements OnDestroy {
@LocalStorage() destroyedVariable: any = {};
ngOnDestroy() {}
}
-
Use the services to manage your data:
import { CookiesStorageService, LocalStorageService, SessionStorageService, SharedStorageService } from 'ngx-store';
export class MyService {
constructor(
localStorageService: LocalStorageService,
sessionStorageService: SessionStorageService,
cookiesStorageService: CookiesStorageService,
sharedStorageService: SharedStorageService,
) {
console.log('all cookies:');
cookiesStorageService.utility.forEach((value, key) => console.log(key + '=', value));
}
public saveSomeData(object: Object, array: Array<any>) {
this.localStorageService.set('someObject', object);
this.sessionStorageService.set('someArray', array);
this.localStorageService.keys.forEach((key) => {
console.log(key + ' =', this.localStorageService.get(key));
});
}
public clearSomeData(): void {
this.localStorageService.clear('decorators');
this.localStorageService.clear('prefix');
this.sessionStorageService.clear('all');
}
}
Note: Always define default value at the property you are using decorator.
Note: Never use for-in
loop on decorated Arrays without filtering by .hasOwnProperty()
.
Note: Please don't ngx-store circular structures as this library uses JSON.stringify to encode data before saving.
Note: When you change prefix from '' (empty string) old values won't be removed automatically to avoid deleting necessary data. You should handle it manually or set clearType to 'all' for some time.
Contributions are welcome!