Load Data with Instance Initializers

Published on Oct 09, 2015

Instance Initializers were introduced in Ember 1.12. By using them you can speed up testing and fastboot.

Learn about the differences between Instance Initializers and Application Initializers, and see how to load custom config data from the server using an Instance Initializer.


Links

Code

//instance-initializers/load-custom-config.js
var GlobalConfig = Ember.Object.extend({
  globals: Ember.computed(function(){
    return $('#global-stash').data('globals')
  }),
  accessoryTypes: Ember.computed('globals', function(){
    return this.get("globals.accessories")
  })
})

export function initialize(application) {
  application.container.register('stuff:global', GlobalConfig)
  application.registry.injection('controller', 'global', 'stuff:global')
}

export default {
  name: 'load-custom-config',
  initialize: initialize
};
//in server template
<div id="global-stash"
        data-globals='{"accessories": ["hats", "boots"]}'>
</div>
//used in a controller
items: Ember.computed.alias('global.accessoryTypes')

Transcript

Hey and welcome back to EmberScreencast. Last time we introduced initializers, specifically application initializers. This time we’re going to introduce instance initializers, and we’ll see how we can load some data before the code even loads.

Here are some of the differences, and we’ll be looking into more of these as we go to our example. So application initializers have been around a lot longer, whereas instance initializers were introduced in 1.12. Application initializers are more flexible, whereas instance initializers, they’re useful for when you’re testing or when you’re running fastboot. They can save you time. The function in the initialize function, it’s called differently. Application initializer has a container and an application, whereas the function instance initializers just give you application as an argument. Application initializers are run first, and instance initializers are run after all the application initializers are run. Application initializers are run once per app boot, whereas instance initializers are run over and over again every time it’s initialized, and that difference comes to the fore when you’re doing testing and when you’re doing fastboots. So instance initializers, they run every single test, whereas application initializers they just run once at the beginning of the test suite, and the same for when you’re doing fastboot. So fastboot can customize stuff for each individual person in the instance initializers, whereas the application initializers they’re going to have the more general stuff, the code loading. And lastly, application initializers can defer readiness, and instance initializers cannot.

Now we’ll go back to our example, Accessor.ly, where we have a list of items and it creates stuff for each item that we can mess around with.

Now this list of items is currently just given as a list of different types of accessories that we can use,

but what if we wanted to have that list in multiple places within the application, or later what if we wanted to load it from the server? Instance initializers let us do that.

So this is our instance initializer. Notice it goes in the instance-initializers folder instead of the initializers folder.

It looks a little bit different than what we saw last time although it’s definitely building off of it. Let me explain those differences. First, I generate this with ember.cli, and so it created the initialize function separately from the initializer that it’s exporting. And then as you see it takes that initialize function, puts it down here under the initialize key. So that looks different, it’s really the same.

The next thing is that, as we said before, instead of container and application, it’s just application, and then we do application.container.register and application. registry.injection. So in instance initializers, well before you could do application.register and application.inject, but those APIs have changed. So this for resgistering and this for injecting. The other parts of the APIs have stayed the same. The arguments that you give it are the exact same. Here you can see we made up something called stuff:global because it requires a name, a colon, and another name. So we just made that up and we stuck our GlobalConfig in it.

And notice the second argument to the register if we try to just feed it this array, it wouldn’t work. It has to be an Ember.Object, something like this. So we create an Ember.Object that currently just has one property, and that’s accessoryTypes, and that’s where we’re sticking our list of accessories.

Going back to our controller,

we need to figure out how to get that list out of the GlobalConfig and into our controller. So here we're doing an Ember.computed.alias, and we have access to global and then we’ll be doing the accessoryTypes, so we’ll get the accessoryTypes property on this GlobalConfig.

So we have hats and boots, and caps. Let’s go ahead and add one. We’ll add scarves back,

and we can see that when we reload, it’s getting the scarves.

So it’s picking it up from this custom-config. But we want to go farther. We want to pick up stuff from the server.

Here’s our server side template.

So as you can see, in data-globals were putting a hash that contains an array under the key accessories. So this will be our globals hash and then we’ll get the accessories from it. We can get other things from it later.

So here in Global.Config, we’ll start by getting the data from globals. We’ll use jquery to grab the global-stash div, and then we’ll get the data from it that’s in data(‘globals’).

So globals is just going to be in JavaScript object, and it’ll be the one we have in here, which in this case is a hash, a hash that has the accessories key on it.

So we’ll take advantage of that and use Ember.computed.alias to get that key off of there, to get the value for that key.

So then we take this to our client and we reload and it is getting the stuff off of the server instead of the stuff we had before.

Now we’re going to take this just one step further and this is being done in Rails, but there’s similar stuff you can do in any server side framework.

So we’re going to take our accessories and we’re going to get it from the controller. And so right now it’s being defined just as an array, but this could easily be pulled from the database or calculated based on what the user is doing.

So of course this also works, and in Rails it works pretty magically getting the JSON correct. In other frameworks you may have a bit more difficult time, but hopefully you won’t.

So there you go. We’re taking a config all the way from your server side controller

through your server side template,

we’re loading it up in an instance initializer and then we’re using it in our controller.

Now you may be wondering, why don’t we just grab it through ajax on the controller instead of doing an instance initializer. And that is a possibility, but I have done that, and it can take a little bit of time each time you load that controller, and that messes with the user’s flow. It’s especially bad if, in the case that I was using it, I was getting the options for a select box. And so select boxes wouldn’t be working for a little while, and this was especially bad because one might have been already selected and their select boxes would be changing midstream while they’re working on their form. The instance initializer approach avoids all that and it means you only have to load it once.

So I hope this helps you when you’re trying to decide when you should use an instance initializer and when you should use an application initializer. I know I learned a lot making this, so go out and initialize.

Subscribe to our mailing list