Problems displaying hasMany relationship with JSONAPI adapter


#1

For my model I have defined a hasMany and want to display in the show template the model attributes as well as the list of hasMany items below it.

My problem is that for some weird reason, while all the hasMany items are returned by the server, only the first record is actually displayed, even when the page is refreshed.

The really weird part is that if I navigate away from the show page (e.g. back to the index listing), select the same item to be shown, all of a sudden the complete list of hasMany items is shown, and stays that way thereafter.

It’s almost like some kind of buffering is taking place, or I could be using it incorrectly.

Here’s what my code looks like, hopefully someon can help me.

/app/models/competition.js:

import DS from 'ember-data';
export default DS.Model.extend({
  name: DS.attr('string'),
  standings: DS.hasMany('standing', { async: true })
});

/app/routes/competitions/show.js:

import Ember from 'ember';
export default Ember.Route.extend({
  model(params) {
    return this.store.findRecord('competition', params.competition_id);
  }
});

/app/templates/competitions/show.js:

<h1>Competition</h1>

<p>
Name : {{model.name}}
</p>

<h2>Standings</h2>
{{table-standings standings=model.standings}}

/app/components/table-standings.js

import Ember from 'ember';
export default Ember.Component.extend({
});

/app/templates/components/table-standings

{{#each standings as |standing|}}
  ...
{{/each}}

From the server:

{
  "data": {
    "id": "10",
    "type": "competitions",
    "attributes": {
      "comp-id": 1229,
      "name": "Bundesliga",
      "created-at": "2017-03-28T20:46:23.526Z",
      "updated-at": "2017-03-28T20:46:35.455Z"
    },
    "relationships": {
      "region": {
        "data": {
          "id": "7",
          "type": "regions"
        }
      },
      "standings": {
        "data": [
          {
            "id": "210",
            "type": "standings"
          },
          {
            "id": "209",
            "type": "standings"
          },
          {
            "id": "208",
            "type": "standings"
          },
          {
            "id": "207",
            "type": "standings"
          },
          {
            "id": "206",
            "type": "standings"
          },
          {
            "id": "205",
            "type": "standings"
          },
          {
            "id": "204",
            "type": "standings"
          },
          {
            "id": "203",
            "type": "standings"
          },
          {
            "id": "202",
            "type": "standings"
          },
          {
            "id": "201",
            "type": "standings"
          },
          {
            "id": "200",
            "type": "standings"
          },
          {
            "id": "199",
            "type": "standings"
          },
          {
            "id": "198",
            "type": "standings"
          },
          {
            "id": "197",
            "type": "standings"
          },
          {
            "id": "196",
            "type": "standings"
          },
          {
            "id": "195",
            "type": "standings"
          },
          {
            "id": "194",
            "type": "standings"
          },
          {
            "id": "193",
            "type": "standings"
          }
        ]
      }
    }
  }
}

Followed by (for each request):

{
  "data": {
    "id": "210",
    "type": "standings",
    "attributes": {
      "comp-id": 1229,
      "season": "2016\/2017",
      "round": 25,
      "stage-id": 12291081,
      "comp-group": null,
      "country": "Germany",
      "team-id": 10329,
      "team-name": "Darmstadt",
      "status": "same",
      "recent-form": "LWLLL",
      "position": 18,
      "overall-gp": 25,
      "overall-w": 4,
      "overall-d": 3,
      "overall-l": 18,
      "overall-gs": 17,
      "overall-ga": 47,
      "home-gp": 13,
      "home-w": 4,
      "home-d": 3,
      "home-l": 6,
      "home-gs": 13,
      "home-ga": 20,
      "away-gp": 12,
      "away-w": 0,
      "away-d": 0,
      "away-l": 12,
      "away-gs": 4,
      "away-ga": 27,
      "gd": -30,
      "points": 15,
      "description": "Relegation - 2. Bundesliga",
      "created-at": "2017-03-28T20:46:35.441Z",
      "updated-at": "2017-03-28T20:46:35.464Z"
    },
    "relationships": {
      "competition": {
        "data": {
          "id": "10",
          "type": "competitions"
        }
      }
    }
  }
}
...

#2

When only one item is displayed, the first time around, how many standing ED records are created (you can check this in the Data tab of the Ember Inspector)?

Has any standings been loaded before you go to that route?


#3

According to the Ember Inspector, I see standings(10):

However, as you can see from the screenshot, only the first item is actually displayed.

(If I look closely, there does seem to be a quick instant in which the tables rows flash and then disappear).

Clicking on the [<- Back]-button takes me back to the index page, and then clicking on the same league takes me back to the same show template, but this time around listing all 10 items:

I wonder of this is some kind of bug.


#4

One workaround which avoids this problem is to ignore the hasMany altogether and just pull in via a store query promise in setupController.

Route:

setupController(controller, model) {
  this._super(controller, model);
  this.store.query('standing', { competition_id: model.get('id')}).then(
    standings => controller.set('standings', standings),
    error => console.error(error)
  )
}

Template:

<h1>Standings: {{standings.length}}</h1>
{{table-standings standings=standings}}

But of course this is abusing the whole idea behind JSONAPI, and there should be a more elegant and proper solution.


#5

Problem has been solved.

I removed the league: DS.belongsTo('league) relationship in the standing model, and everything works just fine now.