Ember Data uses a single data store that can be accessed throughout an application. In this example, we'll create a simple application that retrieves a list of books and displays it to the user.
Before we begin, we'll need to mock data for our server. Ember CLI has a built-in mock server that can handle this situation by generating a basic Express server. However, for the purposes of this recipe, we'll go ahead and use the Ember CLI Mirage add-on. It has more features and is easier to use. You can find more information about Ember CLI Mirage at https://github.com/samselikoff/ember-cli-mirage.
$ ember new BookExample
$ cd BookExample $ ember install ember-cli-mirage $ ember g factory book
This will install the latest Bower and npm
packages needed and create the book
factory for Mirage.
To make this recipe work, we'll need to mock book data.
config.js
file in the app/mirage
folder:// app/mirage/config.js export default function() { this.get('/books'); this.get('/books/:id'); }
This configuration file will set the fake routes that we need for our data. The /books
route will return all the book data and the /books/:id
route will return individual books based on the ID passed in the URL.
book.js
file in the app/mirage/factories
folder. Add the following properties:// app/mirage/factories/book.js import Mirage, {faker} from 'ember-cli-mirage'; export default Mirage.Factory.extend({ title: faker.lorem.sentence, // using faker author() {return faker.name.findName(); }, year: faker.date.past });
This file sets the properties that we'll use later for our model. The title
property refers to the name of the book, author
refers to the person who wrote the book, and year
is the year it was published. To make things a little easier, Ember CLI Mirage includes a library called faker
. This library generates data that we can use to populate our in-memory data store.
default.js
file in the app/mirage/scenarios
folder:export default function( server ) { server.createList('book',10); }
Make sure to delete the comments around server
. This scenario will generate ten new 'book'
records every time the browser is loaded. After the browser is loaded, the books will be generated via the factory.
$ ember g model book title:string author:string year:date $ ember g adapter application $ ember g route books $ ember g route application
This command will generate a new model called book
, and set the title
, author
, and year
as properties in this model. The generate adapter
command will create a new adapter for our application, while the last commands will generate routes for the book
and application
.
book.js
file in the app/models
folder. It should look as follows:// app/models/book.js import DS from 'ember-data'; export default DS.Model.extend({ title: DS.attr('string'), author: DS.attr('string'), year: DS.attr('date') });
The models
file is a representation of the data that we'll be using. We can use three different types of data: string
, number
, or date
. This data will be loaded from our mock server.
application.js
file created in the app/adapters
folder:// app/adapters/application.js import DS from 'ember-data'; export default DS.RESTAdapter.extend({ });
Ember Data has several adapters available for it. One of the easiest to use is the REST adapter.
{ "books": [ { "id": 1, "title": "Some title", "author": "Authors name", "date": "1980-05-23" } { "id": 2, "title": "Some other title", "author": "Authors name 2", "date": "1985-05-23" } ] }
The preceding JSON lists an array of books. If, by chance, only one record was returned, the REST adapter would expect the array to be named book
and not books
. Keep in mind that you should camel-case all record names and the data should be in the REST adapter format.
application.js
file in the app/routes
folder. Add a new model that returns all the books listed:// app/routes/application.js import Ember from 'ember'; export default Ember.Route.extend({ model(){ return this.store.findAll('book'); } });
As discussed in Chapter 4, Ember Router, one of the responsibilities of the route is returning the model data. The Ember Data store has a method called findAll
that will return all the data from the book
model. By convention, the Ember application will execute an HTTP GET to the /book/ URL
and expect a JSON payload in response. As this model is in the application route, it can be accessed in any template.
application.hbs
file and display the new data from the mock server:// app/templates/application.hbs {{#link-to 'index'}}<h2 id="title">Welcome to Ember</h2>{{/link-to}} {{outlet}} {{#each model as |book|}} <br> title: {{#link-to 'books' book.id}}{{book.title}}{{/link-to}}<br> {{/each}}
This template uses the each
helper to iterate though all the data that is returned from the model
hook after the page loads. The link-to
helper will pass book.id
in the URL as an argument. We'll use the book title
as the link.
// app/routes/books.js import Ember from 'ember'; export default Ember.Route.extend({ model(params){ return this.store.findRecord('book',params.book_id); } });
The model
hook receives a parameter from the URL. The findRecord
Ember Data can be used to find individual records. It will make an HTTP GET request to the /books/:id
URL when the model
hook is loaded. The first argument is the data store and the second is the record ID.
router.js
file in the app
folder with the new dynamic route for books
:// app/router.js import Ember from 'ember'; import config from './config/environment'; var Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('books', {path:'/books/:book_id'}); }); export default Router;
This new route for books
has a path of /books/:book_id
. To access the books
route, you have to submit an ID in the path.
books.hbs
template:// app/templates/books.hbs {{outlet}} <br> <b>Author: {{model.author}}</b><br> <b>Year: {{model.year}}</b> <br>
Accessing this route will trigger the model
hook. This will render author
and year
of the book selected.
ember server
and open a web browser. You'll see a list of all the titles with links to each individual book:Each post has a unique ID. Clicking on a link will display the title and author of that book.
Models represent data in Ember. These models can use Ember Data to store, update, and retrieve data from a server. The data from the server is usually sent in the JSON format. Ember offers a handful of adapters to the interface with the data coming from the server. The REST adapter is the most commonly used. It expects data in a certain format so that Ember can parse, store, and display it to the user.
Ember Data caches the data after it retrieves the data from the server. This minimizes the amount of round-trips to the server. However, Ember Data will make a request in the background whenever a cached data record is returned from the store. If the data has changed, it will be rerendered on the screen.