dscheerens / ngx-webstorage-service

Module for Angular that provides service wrappers for the Web Storage API
MIT License
65 stars 11 forks source link

Build Status NPM Version

Webstorage services for Angular

This package provides service wrappers for the Web Storage API. Whenever your application needs to use localStorage or sessionStorage, instead of using them directly you can make use of the wrapped versions provided by this package. Doing so has the following advantages:

Installation

Simply add the ngx-webstorage-service module to your package.json file by executing the following command:

npm install --save ngx-webstorage-service

After having installed the ngx-webstorage-service package you might need to update your project configuration depending on the build tools you use (e.g. when using SystemJS).

The ngx-webstorage-service package is published in the Angular Package Format.

Angular version compatibility matrix

Use the compatibility matrix below to determine which version of this module works with your project's Angular version.

Library version Angular version
angular-webstorage-service - 1.x.x >= 4.0.0
ngx-webstorage-service - 2.x.x >= 4.0.0
ngx-webstorage-service - 3.x.x >= 5.0.0
ngx-webstorage-service - 4.x.x >= 7.0.0
ngx-webstorage-service - 5.x.x >= 13.0.0

Usage

To make use of the (web) storage services in your application inject the storage services into your own classes. For example to make use of session storage import the SESSION_STORAGE injection token, together with the StorageService interface, and use those to inject the session storage service. The code snippet below shows an example.

import { Inject, Injectable } from '@angular/core';
import { SESSION_STORAGE, StorageService } from 'ngx-webstorage-service';

const STORAGE_KEY = 'pure-awesomeness';

@Injectable()
export class MyAwesomeService {

    constructor(@Inject(SESSION_STORAGE) private storage: StorageService) {

    }

    public doSomethingAwesome(): number {
        const awesomenessLevel: number = this.storage.get(STORAGE_KEY) || 1337;
        this.storage.set(STORAGE_KEY, awesomenessLevel + 1);
        return awesomenessLevel;
    }
}

One thing you have to keep in mind while designing your own application or library that makes use of this package, is to think about reusability and maintainability of the classes that are going to depend on the StorageService interface. Instead of directly using the SESSION_STORAGE or LOCAL_STORAGE injection tokens it might be wise to introduce your own injection token. For the code example above you could do it like this:

export const MY_AWESOME_SERVICE_STORAGE =
    new InjectionToken<StorageService>('MY_AWESOME_SERVICE_STORAGE');

@Injectable()
export class MyAwesomeService {

    constructor(
        @Inject(MY_AWESOME_SERVICE_STORAGE) private storage: StorageService
    ) {

    }

    // ...
}

Then, in your module definition, you can create a provider for the injection token like so:

import { NgModule } from '@angular/core';
import { SESSION_STORAGE } from 'ngx-webstorage-service';

import { MY_AWESOME_SERVICE_STORAGE, MyAwesomeService } from './my-awesome-service';

@NgModule({
    providers: [
        { provide: MY_AWESOME_SERVICE_STORAGE, useExisting: SESSION_STORAGE },
        MyAwesomeService
    ]
})
export class AwesomeModule {

}

By introducing your own injection token you'll give users of your API more control over what type of storage to use. This makes it easier for the user to select the appropriate type of storage. In general it should not matter anyway which type of storage is used from the perspective of the API you are developing (it only needs to store data). The specific application of the API governs which type of storage is appropriate.

API

The heart of this package is the StorageService<T> interface. This interface has the following functions:

Two implementations of the StorageService are provided by this package:

In case you want to check whether localStorage and sessionStorage are available within the current browser yourself, you can make use of the isStorageAvailable function. This function accepts one parameter of type Storage (which is part of the HTML 5 specification) and returns a boolean that indicates whether the storage is available. An example use of the function is shown below:

import { isStorageAvailable } from 'ngx-webstorage-service';

const sessionStorageAvailable = isStorageAvailable(sessionStorage);

console.log(`Session storage available: ${sessionStorageAvailable}`);

Storage transcoders

With the release of version 3.0.0 of ngx-webstorage-service the concept of storage transcoding has been introduced. A storage transcoder determines what type of values can be stored and retrieved by a StorageService instance. This is reflected by the type parameter T in the StorageService interface. By default any type of value can be stored as long as it can be represented by a JSON string. Hence the type parameter T defaults to any.

Sometimes, however, you might prefer to store the data in another format than JSON strings, for example if values are read/written by a third party library that uses a different format. This is often the case when the stored value is just a string. Since values are read/written as JSON strings a normal string will be wrapped in quotes by default (as this is how strings are encoded in JSON format). If the third party library writes string values without quotes, then ngx-webstorage-service will not be able to read the value, because it is not a valid JSON string.

This problem can be addressed by using a different transcoder, which is illustrated in the following example:

import { Inject, Injectable } from '@angular/core';
import { SESSION_STORAGE, StorageService, StorageTranscoders } from 'ngx-webstorage-service';

@Injectable()
export class MyAwesomeService {

    constructor(@Inject(SESSION_STORAGE) storage: StorageService) {
        // Mimic third party storing a value...
        sessionStorage.setItem('foo', 'bar');

        // Retrieve value...
        storage.get('foo'); // undefined :(
        storage.get('foo', StorageTranscoders.STRING); // 'bar' :)
    }
}

Both the get and set functions of the StorageService have been overloaded to accept an optional StorageTranscoder. If you only use one type of transcoder for the storage service (other than JSON), then you can also make use of the withDefaultTranscoder function of the StorageService interface to create a new instance that uses the specified transcoder by default. An example of this is shown below:

import { Inject, Injectable } from '@angular/core';
import { SESSION_STORAGE, StorageService, StorageTranscoders } from 'ngx-webstorage-service';

@Injectable()
export class AnsweringService {

    private numberStorage: StorageService<number>

    constructor(@Inject(SESSION_STORAGE) storage: StorageService) {
        this.numberStorage = storage.withDefaultTranscoder(StorageTranscoders.NUMBER);
    }

    public get theAnswer(): number {
        return numberStorage.get('answer');
    }

    public set theAnswer(value: number) {
        return numberStorage.set('answer', value);
    }
}

The following storage transcoders are available:

It is also possible to create your own transcoder by defining an object that conforms to the StorageTranscoder interface.