Search code examples
modelcontrollerember.jsrelationshipember-data

Access to attributes from relationship on ember-data models


I'm working on a small application like a Social Network to manage projects. Right now, I'm working on friendship relations on the network. For that I've created a model called 'Person' with the next attributes:

App.Person = DS.Model.extend
(
   {
      name: DS.attr('string'),
      place: DS.attr('string'),
      email: DS.attr('string'),
      password: DS.attr('string'),
      academic: DS.attr('string'),
      professional: DS.hasMany('App.Work'),
      knowledge: DS.attr('string'),
      projects: DS.hasMany('App.Project'),
      friends: DS.hasMany('App.Person')
   }
);

Now, I'm trying to get the list of friends of a person in the controller, but I don't know how to access to this. Trying something like this.get('model').get('friends') show in the template a string like <DS.ManyArray:ember358>. What's the right way to access to this? Should it be done on the Controller, on the Route, should I create an additional View or something like that?

Thanks a lot in advance for your help.


EDIT:

I've added exactly what @ArturMalecki said but I'm getting <DS.ManyArray:ember360>. This is what I've got:

Person Controller

App.PersonController = Ember.ObjectController.extend
(
  {
    friends: function() 
    {
      return this.get('model').get('friends');
    }.property('model.friends'),
  }
);

Router

App.Router.map
(
  function()
  {
    this.resource('app', { path: '/' }, function ()
    {
      // Additional child routes
      this.route('friends');
      ...
    });
    this.resource('person');
  }
);

App.PersonRoute = Ember.Route.extend
(
  {
    model: function()
    {
      return App.Person.find();
    }
  }
);

App.AppFriendsRoute = Ember.Route.extend
(
  {
    model: function()
    {
      return App.Person.find();
    }
  }
);

Handlebars template

<script type="text/x-handlebars" data-template-name="app/friends">
  <h1>Friends</h1>
  <ul>
    {{#each model itemController="person"}}
      <li>{{name}}, from {{place}}. Him/her friends are <{{friends}}>
    {{else}}
      You've no still friends
    {{/each}}
  </ul>
</script>

Output

Friends

<person1>, from <place1>. Him/her friends are <<DS.ManyArray:ember360>>
<person2>, from <place2>. Him/her friends are <<DS.ManyArray:ember361>>
<person3>, from <place3>. Him/her friends are <<DS.ManyArray:ember362>>

By the way, I've been trying to get something working, and it actually works, but I'm sure it's not the optimal solution and probably it's not a good practice either. Certainly is not applicable for every case:

friends: function()
{
  var model = this.get('model');

  var friendsList = model.get('friends').mapProperty('name');

  return friendsList;
}.property('model.friends'),

Solution

  • First in your route you need to set up model. Lets assumed that you have PersonRoute and PersonController

    App.PersonRoute = Ember.Route.extend({
      model: function() {
        return App.Person.find()
      }
    });
    

    Then you can access to friends property in the controller in this way:

    App.PersonController = Ember.ObjectController.extend({
      someCustomMethod: function() {
        ...
        this.get('model').get('friends');
        ...
      },
    })
    

    Remember that you need to add person to the routes:

    App.Router.map(function() {
     this.resource("person");
    });
    

    Update

    Simple example how to use hasMany relation in view http://jsfiddle.net/Mwg89/10/

    HTML

    <script type="text/x-handlebars" data-template-name="application">
        {{outlet}}
    </script>
    <script type="text/x-handlebars" data-template-name="index">
        {{#each friend in friends}}
          {{friend.name}}
        {{/each}}
        <hr/>
        {{#each friend in model.friends}}
          {{friend.name}}
        {{/each}}
    </script>
    

    JS

    App = Ember.Application.create({});
    
    App.Store = DS.Store.extend({
        revision: 12,
        adapter: 'DS.FixtureAdapter'
    });
    
    App.Person = DS.Model.extend({
        name: DS.attr('string'),
        friends: DS.hasMany('App.Person'),
    });
    
    App.Person.FIXTURES = [
        { id: 1, name: 'Person1', friends: [2,3] },
        { id: 2, name: 'FriendPerson1' },
        { id: 3, name: 'FreindPerson2' }
    
    ];
    
    App.IndexRoute = Ember.Route.extend({
        model: function() {
            return App.Person.find(1);
        }
    });
    
    App.IndexController = Ember.ObjectController.extend({
        friends: function() {
            return this.get('model').get('friends');
        }.property('model.friends')
    })