Reputation: 7592
Given these JSON data models on a RESTful server
/users
{"users":[
{"id":"1","first_name":"John","last_name":"Doe"},
{"id":"2","first_name":"Donald","last_name":"Duck"}
]}
/users/1
{"user":
{"id":"1","first_name":"John","last_name":"Doe","account":"1"}
}
/accounts
{"accounts":[
{"id":"1","owned_by":"1"},{"id":"2","owned_by":"2"}
]}
/accounts/1
{"account":
{"id":"1","owned_by":"1","transactions":[1,17]}
}
and these Ember data models
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter.create({
url: 'http://api.mydomain.ca'
})
});
App.User = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
account: DS.belongsTo('App.Account')
});
App.Account = DS.Model.extend({
ownedBy: DS.belongsTo('App.User'),
transactions: DS.hasMany('App.Transaction')
});
what other ember code do I have to write to load the data into the models and then write a template that outputs a user's name, account id, and the number of transactions in the account?
Upvotes: 6
Views: 2734
Reputation: 7592
I was able to solve this so I will post my code in case it helps someone else. The trick is to make sure the JSON data is formatted exactly how Ember wants it and to create the proper routes.
From what I can tell, Ember expects parent objects to provide a list of child objects. This feels weird to me so if anyone knows a way to do it with child objects referencing their parents with a foreign key please let me know.
I changed the account property on my /user/:user_id JSON object to account_id I also included the account_id on the user objects found at /users and I changed the owned_by property on the account to user_id.
My javascript file
var App = Ember.Application.create();
// Router
App.Router.map(function() {
this.resource('users', function() {
this.resource('user', {path:':user_id'});
}); // '/#/users/:user_id'
this.resource('accounts', function() {
this.resource('account', {path:':account_id'});
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('users');
}
});
App.UsersRoute = Ember.Route.extend({
model: function() {
return App.User.find();
}
});
App.AccountsRoute = Ember.Route.extend({
model: function() {
return App.Account.find();
}
});
// Controllers
App.TransactionsController = Ember.ArrayController.extend();
// Adapter
App.Adapter = DS.RESTAdapter.extend({
url: 'http://api.mydomain.ca'
});
// Models
App.Store = DS.Store.extend({
revision: 11,
adapter: App.Adapter.create({})
});
App.User = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
account: DS.belongsTo('App.Account')
});
App.Account = DS.Model.extend({
user: DS.belongsTo('App.User'),
transactions: DS.hasMany('App.Transaction'),
balance: function() {
return this.get('transactions').getEach('amount').reduce(function(accum, item) {
return accum + item;
}, 0);
}.property('[email protected]')
});
App.Transaction = DS.Model.extend({
account: DS.belongsTo('App.Account'),
amount: DS.attr('number'),
description: DS.attr('string'),
timestamp: DS.attr('date')
});
And the handlebars templates
<script type="text/x-handlebars" data-template-name="application">
<div class="row">
<div class="twelve columns">
<h2>Accounts</h2>
<p>{{outlet}}</p>
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="users">
<div class="row">
<div class="three columns" id="users">
{{#each user in controller }}
{{#linkTo "user" user class="panel twelve columns"}}{{user.firstName}} {{user.lastName}}{{/linkTo}}
{{/each}}
</div>
<div class="nine columns" id="user">
{{ outlet }}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="user">
<h2>{{firstName}} {{lastName}}</h2>
{{#if account}}
{{render "account" account}}
{{else}}
Error: Account not set up!
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="accounts">
<div class="row">
<div class="three columns" id="accounts">
{{#each account in controller }}
{{#linkTo "account" account class="panel twelve columns"}}{{account.id}} {{account.user.firstName}} {{account.user.lastName}}{{/linkTo}}
{{/each}}
</div>
<div class="nine columns" id="account">
{{ outlet }}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="account">
<p>Account Number: {{id}}, Balance: {{balance}}, {{transactions.length}} transactions</p>
{{render "transactions" transactions}}
</script>
<script type="text/x-handlebars" data-template-name="transactions">
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Amount</th>
<th>Timestamp</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{{#each transaction in controller}}
<tr>
<td>{{transaction.id}}</td>
<td>{{transaction.amount}}</td>
<td>{{transaction.timestamp}}</td>
<td>{{transaction.description}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
Upvotes: 3
Reputation: 1
Create a Index route that seeds your IndexController with a model and create a related Template that iterates over your relationships.
Here is an example for a simple HasMany-Relationship between post and comments:
var App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter.create()
});
App.Post = DS.Model.extend({
comments: DS.hasMany('App.Comment')
});
App.Comment = DS.Model.extend({
post: DS.belongsTo('App.Post'),
body: DS.attr('string'),
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('content', App.Post.find("1"));
}
});
The HTML-Code should look like this:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<script type="text/x-handlebars" data-template-name="index">
{{#each comment in content.comments}}
{{comment.body}}
{{/each}}
</script>
</body>
And the last but not least the server response /posts/1
{
"post": {
"id": 1,
"title": "Rails is omakase",
"comments": [1, 2, 3]
},
"comments": [{
"id": 1,
"body": "But is it _lightweight_ omakase?"
},
{
"id": 2,
"body": "I for one welcome our new omakase overlords"
},
{
"id": 3,
"body": "Put me on the fast track to a delicious dinner"
}]
}
Upvotes: 0