Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use HTML5 Local Storage with Ember.js?

I would like to use HTML5 Local Storage with my Ember.js.

I haven't been able to find any examples of doing this without Ember Data.

How should this be done? What do I need to consider?

like image 507
Taras Mankovski Avatar asked Aug 30 '13 08:08

Taras Mankovski


2 Answers

So let's say we have an object called Storage that in our real-world implementation would represent an adapter-like object for the localStorage to store and retrieve data:

App.Storage = Ember.Object.extend({
  init: function() {
    this.clearStorage();

    var items = ['foo', 'bar', 'baz'];
    localStorage.items = JSON.stringify(items);
  },
  find: function(key) {
    // pseudo implementation
    if( !Ember.isNone(key) ) {
      var items = [];
      var storedItems = JSON.parse(localStorage[key]);
      storedItems.forEach(function(item){
        items.pushObject(item);
      });
      return items;
    }
  },
  clearStorage: function() {
    // pseudo implementation
    localStorage.clear();
  }
});

Beside the pseudo implementations, you can see there is a dummy array with some data stored at object initialization, we will use this later in our IndexRoute model hook to retrieve it, just to show that this works.

Now to the more nice stuff, you could do the register & inject directly after the application is ready, but what if we wanted it to be already available at application initialization? Well "there an ember-feature for that", called Application.initializer, initializer are simple classes with a 'name' property and a initialize function in where you have access to your application container and do what ever needs to be done, let me explain this in code:

To be notified when the application start loading we can listen to the onLoad event to create our initializer classes that will register and inject the before mentioned Storage object into every controller and every route:

Ember.onLoad('Ember.Application', function(Application) {
 // Initializer for registering the Storage Object
  Application.initializer({
    name: "registerStorage",
    initialize: function(container, application) {
      application.register('storage:main', application.Storage, {singleton: true});
    }
  });
 // Initializer for injecting the Storage Object
  Application.initializer({
    name: "injectStorage",

    initialize: function(container, application) {
      application.inject('controller', 'storage', 'storage:main');
      application.inject('route', 'storage', 'storage:main');
    }
  });
});

Now, since the Storage object was injected into every route and every controller we can finally get access to it in our IndexRoute model hook and make the stores array mentioned above available trough the call self.get('storage').find('items') to our template to be rendered (just added a promise to make it actually conform with the ember-way and with some fictive delay, rather than just returning the array):

App.IndexRoute = Ember.Route.extend({
  model: function(){
    var self = this;
    var promise = new Ember.RSVP.Promise(function(resolve) {
      Ember.run.later(function() {
        var data = self.get('storage').find('items');
        console.log(data);
        resolve(data);
      }, 1000);
    });

    return promise;
  }
});

In our index template we can now agnostically loop over the dummy array not caring where it is coming from:

<script type="text/x-handlebars" id="index">
  <h2>Index</h2>
  <ul>
    {{#each item in model}}
      <li>Item: {{item}}</li>
    {{/each}}
  </ul>
</script>

And lastly, you can see here all the above explained in a working example: http://jsbin.com/eqAfeP/2/edit

Hope it helps.

like image 112
intuitivepixel Avatar answered Oct 12 '22 03:10

intuitivepixel


The accepted answer is great, but I thought I would add this alternative:

Dan Gebhardt has created a very interesting library called Orbit.js for coordinating different data sources on a client. There are three out of the box data sources: memory, local storage, and json api.

For ember integration, check out ember-orbit.

It is still under heavy development at this time, and it introduces a different paradigm than Ember Data, so proceed with caution!

like image 1
leejt489 Avatar answered Oct 12 '22 04:10

leejt489