0

I am having some trouble loading relationship data using Ember 2.0. Given the following two models, Project and LineItem, I am trying to list all line items belonging to a given project:

export default DS.Model.extend({
    name: DS.attr(),
    organisation: DS.attr(),
    customer: DS.attr(),
    hours: DS.attr({defaultValue: 0}),
    line_items: DS.hasMany('line-item', {async: true})  
});

export default DS.Model.extend({
    name: DS.attr(),
    value: DS.attr({defaultValue: 1}),
    quantity: DS.attr({defaultValue: 1}),
    state: DS.attr({defaultValue: 'OPEN'}),
    project: DS.belongsTo('project')
});

Inside my route, I load a given project without problems:

export default Ember.Route.extend(AuthenticatedRouteMixin, {
    model(params) {
        return this.store.findRecord('project', params.project_id);
    }
});

Inside my component, I then try to load my line items as follows:

import Ember from 'ember';

export default Ember.Component.extend({
    store: Ember.inject.service(),
    lineItems: function () {
        return this.get('project').get('line_items').toArray();
    }.property('project.line_items'),
});

When I try to iterate over my line items inside my template however, nothing happens:

{{#each lineItems as |item|}}
   <tr>
     <td>
        <a href="#">{{item.name}}</a>
     </td>
   </tr>
{{/each}} 

No luck using {{#each project.line_items as |item|}} either. Printing the output of this.get('project').get('line_items').toArray() shows an empty list.

However my project contains line items, as expected:

{  
   "data":{  
      "type":"projects",
      "id":"7d93633d-a264-4cb3-918c-82cc44cb76e2",
      "attributes":{  
         "created":"2016-04-04T19:02:03.113408Z",
         "modified":"2016-04-04T19:02:03.113511Z",
         "name":"Sample name",
         "hours":0
      },
      "relationships":{  
         "line_items":{  
            "meta":{  
               "count":1
            },
            "data":[  
               {  
                  "type":"LineItem",
                  "id":"01915d73-fde5-4b6f-8915-174c16592942"
               }
            ]
         }
      }
   }
}

...my line item:

      {
            "type": "line-items",
            "id": "01915d73-fde5-4b6f-8915-174c16592942",
            "attributes": {
                "created": "2016-04-04T19:02:15.622483Z",
                "modified": "2016-04-04T19:02:15.622534Z",
                "name": "Test Line Item",
                "value": 1,
                "quantity": 1
            },
            "relationships": {
                "project": {
                    "data": {
                        "type": "projects",
                        "id": "7d93633d-a264-4cb3-918c-82cc44cb76e2"
                    }
                }
            }
        }
JB2
  • 1,587
  • 2
  • 24
  • 40
  • 1
    I tested your code and yep, it is not working. It works only if I rename the model "item" and "items" everywhere. It looks to me, that Ember Data doesn't like concatenated model names.... – Zoltan Apr 05 '16 at 08:40
  • Thanks Zoltan! You mean instead of the model name `line-item` it should be called `items`? – JB2 Apr 05 '16 at 20:07
  • 1
    That was it Zoltan. Thank you - this solved it! – JB2 Apr 05 '16 at 22:43
  • Well done! I just extracted my comment in a real answer, so you can accept it, if it helped and we can close this question. ;) – Zoltan Apr 07 '16 at 11:09

2 Answers2

1

I tested your code and yep, it is not working. It works only if I rename the model "item" and "items" everywhere. It looks to me, that Ember Data doesn't like concatenated model names...

So, as a conclusion, we should use simple name everywhere, or have to figure out the exact syntax... camelCase, dash-erized or under_scored?

Zoltan
  • 4,936
  • 1
  • 35
  • 40
  • 1
    It seems that `_` is converted to `-` by Ember. So, updating fields will automatically result in the field name being converted to its dasherized equivalent. Which results in all sorts of confusion. Key is to use camelCase :) Thanks again! – JB2 Apr 07 '16 at 11:19
0

I would suggest to do following: Load the project in your route as you do it now. Pass the project instance into the component instead of injecting store instance.

// template which gets rendered after model() hook
...
{{#if model}}
  {{!-- pass the model into your component as 'project' --}}
  {{your-component project=model}}
{{/if}}
...

In your component template you can check if asynchronously loaded relationships have been loaded and show appropriate section afterwards:

// template which gets rendered by your component as the project instance is present 
{{#if project.line_items}} {{!-- #if project.lineItems --}}
  {{!-- iterate over line items and print their names --}}
  <ul>
  {{#each project.line_items as |item|}}
   <li>Line item name: {{item.name}}</li>
  {{/each}}
  </ul>
{{/if}}
...

If everything goes well, this should work. Your component needs no store to be injected, nor any computed property on project.line_items.

Pavol
  • 1,200
  • 8
  • 20
  • Thanks Pavol. I'm afraid that is what I am already doing (i.e. passing the project instance into the component :) -- which works as expected, except for the fact that it seems to contain no line items). – JB2 Apr 05 '16 at 20:05