Skip to content

jelhan/ember-local-storage-decorator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ember Local Storage Decorator

Decorator to use localStorage and sessionStorage in Ember.

Compatibility

  • Ember.js v5.12 or above
  • Embroider or ember-auto-import v2

Installation

ember install ember-local-storage-decorator

Usage

This addon provides two decorators: @localStorage and @sessionStorage. Both work identically, the only difference is the backing storage used. @localStorage persists data in window.localStorage available across browser sessions, while @sessionStorage persists data in window.sessionStorage only for the duration of the current page session.

import { localStorage, sessionStorage } from 'ember-local-storage-decorator';
import Component from '@glimmer/component';

export default class MyComponent extends Component {
  @localStorage foo;
  @sessionStorage bar;
}

Decorate a class property with @localStorage or @sessionStorage to bind it to the respective storage. It will attach a getter to read the value from storage and a setter to write changes to storage.

const Klass = class {
  @localStorage foo;
  @sessionStorage bar;
}
const klass = new Klass();

klass.foo = 'baz';
window.localStorage.getItem('foo'); // '"baz"'

klass.bar = 'qux';
window.sessionStorage.getItem('bar'); // '"qux"'

You may specify another key to be used in storage as an argument to the decorator.

const Klass = class {
  @localStorage('bar') foo;
  @sessionStorage('baz') qux;
};
const klass = new Klass();

klass.foo = 'baz';
window.localStorage.getItem('bar'); // '"baz"'

klass.qux = 'quux';
window.sessionStorage.getItem('baz'); // '"quux"'

The value is stored as a JSON string in storage. Therefore only values which can be serialized to JSON are supported.

Objects (and arrays) are deep frozen to avoid leaking state. Getter returns a frozen copy after setting a value.

window.localStorage.setItem('foo', [{ a: 'b' }]);

const Klass = class {
  @localStorage foo;
};
const klass = new Klass();

Object.isFrozen(klass.foo); // true
Object.isFrozen(klass.foo[0]); // true

const newValue = {};
klass.foo = newValue;

Object.isFrozen(klass.foo); // true
Object.isFrozen(newValue); // false

It observes changes caused by other classes or by other instances:

const KlassA = class {
  @localStorage foo;
};
const KlassB = class {
  @localStorage foo;
}
const klassA = new KlassA();
const klassB = new KlassB();

klassA.foo = 'bar';
klassB.foo; // 'bar'

window.dispatchEvent(
  new StorageEvent('storage', { key: 'foo', newValue: 'baz', oldValue: 'bar' })
);
klassA.foo; // 'baz'
klassB.foo; // 'baz'

Due to limitations of the Web Storage API, direct changes to the storage bypassing the decorator can not be observed. Therefore you should not manipulate window.localStorage or window.sessionStorage directly.

Testing

window.localStorage and window.sessionStorage are global state, which is shared between test runs. The decorators use a global cache, which is also shared between instances. Both are not reset automatically between test jobs.

To avoid leaking state between test jobs it's recommended to clear the cache of @localStorage and @sessionStorage decorators before each test. clearLocalStorageCache and clearSessionStorageCache helper functions are exported from ember-local-storage-decorator to do so.

Additionally window.localStorage and window.sessionStorage should be either cleared before each test run or mocked.

import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { clearLocalStorageCache, clearSessionStorageCache } from 'ember-local-storage-decorator';

module('Integration | Component | my-component', function (hooks) {
  setupRenderingTest(hooks);

  hooks.beforeEach(function () {
    clearLocalStorageCache();
    clearSessionStorageCache();
    window.localStorage.clear();
    window.sessionStorage.clear();
  });
});

@localStorage and @sessionStorage decorators perform some initialization work when a property is decorated. This includes picking up the current value from local storage or session storage and adding it to its internal cache. Manual changes to local storage or session storage after a property has been decorated are not picked up. As class instances are often shared between test jobs, you need to manual reinitialize a local storage or session storage key in tests.

import { initializeLocalStorageKey, initializeSessionStorageKey } from 'ember-local-storage-decorator';

test('some code relying on a value in local storage', function() {
  window.localStorage.setItem('foo', 'bar');
  initializeLocalStorageKey('foo');
});

test('some code relying on a value in session storage', function() {
  window.sessionStorage.setItem('foo', 'bar');
  initializeSessionStorageKey('foo');
});

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

About

Decorator for Ember.js to read and persist data in localStorage

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 8