Subscribe now

Setting up Models and Adapters [09.12.2016]

In the last drip we set up some components and actions in our contact-manager Ember application. If you need to clone the app you can find a link to the repo in the episode notes. We are going to continue working on that app today by discussing and setting up a Contact model and an adapter that will help us connect our Ember app to a server.

Setup

You should have a server application running locally on port 4000. I have a super basic express app that you can clone and setup if you need.

The server code above serves some fixtures in a JSON API compliant payload. Now that we have all that set up, we can get to the Ember stuff. To run that just type:

node index.js

And we can confirm that it is working by opening http://localhost:4000/contacts in our browser.

The Ember Stuff

The first thing we are going to want to do is let Ember Data handle our data instead of manually creating an array and a couple of objects in the route. Let's go ahead and create a model for our contacts.

cd /path/to/ember/project
$ ember g model contact firstName:string lastName:string email:string phone:string

Our newly generated model at app/models/contact.js looks like this:

import Model from 'ember-data/model';
import attr from 'ember-data/attr';
// import { belongsTo, hasMany } from 'ember-data/relationships';

export default Model.extend({
  firstName: attr('string'),
  lastName: attr('string'),
  email: attr('string'),
  phone: attr('string')
});

Here all of our attributes are strings. By default Ember Data gives us four types: string, number, boolean and date. We can also define our own transforms. You can also specify your model's relationships here.

Let's revisit something we looked at briefly earlier: computed properties. Let's add a fullName computed property to our model. In our models we have to remember to import Ember if we want to use Ember's methods like computed.

import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import Ember from 'ember';
// import { belongsTo, hasMany } from 'ember-data/relationships';

export default Model.extend({
  firstName: attr('string'),
  lastName: attr('string'),
  email: attr('string'),
  phone: attr('string'),

  fullName: Ember.computed('firstName', 'lastName', function() {
    return `${this.get('firstName')}  ${this.get('lastName')}`;
  })
});

If you are not familiar with this syntax, we are using an ES2015 feature called template literals. These are just string literals that allow for expression interpolation and multiline string creation. Ember CLI includes babel to transpile ES2015 code to ES5 code so you get access to really neat language features like template literals and arrow functions. Back to the computed property above, it is worth noting that you can set computed properties as well as get them. We will look more at that in a future episode.

To use our model's new computed property we would call it in our template in exactly the same way we would call any other properties on our model. {{model.fullName}}

Now, we can change the template to call that new computed property. In app/templates/contacts.hbs:

<ul>
  {{#each sortedContacts as |contact|}}
  <li>{{contact.fullName}}</li>
  {{/each}}
</ul>

Now we need to update the model hook in our contacts route to pull from Ember Data.

model(){
  return this.store.findAll('contact');
}

If you have one of our server apps running locally at port 4000, there should only be one more step you need to take to wire up the Ember app. We just need to tell it where to look for its data. We do this by generating an adapter.

$ ember g adapter application

Your newly generated adapter at app/adapters/application.js looks like this:

import JSONAPIAdapter from 'ember-data/adapters/json-api';

export default JSONAPIAdapter.extend({
});

We should change it to include a host property:

import JSONAPIAdapter from 'ember-data/adapters/json-api';

export default JSONAPIAdapter.extend({
  host: 'http://localhost:4000'
});

Now, our Ember app is hooked up to our server and serving data from the API.

There are several methods and properties that you can customize on the JSONAPIAdapter class. The host, headers, and namespace properties are likely the ones that you will most often find yourself needing to customize.

// if our api is namespaced we would specify that here
namespace: 'api/v2',
headers: {
  "SOME_KEY": "some value"
}

Now, if we run our Ember app and visit http://localhost:4200/contacts we will see a list of our contacts.

Notes

Resources