Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use multiple ember data models in one view

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?

like image 299
Devin Crossman Avatar asked Jan 29 '13 04:01

Devin Crossman


1 Answers

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>
like image 113
Devin Crossman Avatar answered Nov 14 '22 01:11

Devin Crossman