akst
akst

Reputation: 956

Accessing the `links` property from a ember data query

When using the JSONAPIAdaper, and I query the store for models, the server response include the "links" property specified by json-api spec, with a response like so.

{
  "links": {
    "self": "http://localhost:4200/api/v0/blog-posts?size=10",
    "first": "http://localhost:4200/api/v0/blog-posts?size=10&page=0",
    "last": "http://localhost:4200/api/v0/blog-posts?size=10&page=1",
    "next": "http://localhost:4200/api/v0/blog-posts?size=10&page=1"
  },
  "data": [{
    "id": 1,
    "type": "blog.posts",
    "attributes": {
      "published": "2015-04-04T00:56:36.768Z"
    },
    "relationships": {
      "revisions": {
        "data": [
          { "id": 1, "type": "blog.post.revisions" },
          { "id": 2, "type": "blog.post.revisions" },
          { "id": 3, "type": "blog.post.revisions" },
          { "id": 4, "type": "blog.post.revisions" }
        ]
      },
      "current": {
        "data": { "id": 4, "type": "blog.post.revisions" }
      }
    }
  }]
}

Note: I removed most of the elements in the data property and removed the included property as they make the example unnecessarily large. Also don't worry about the type names, admittedly they look pretty weird but that's how I setup my serialiser (to reflect the pod structure).

The route that requests it looks like this

import Ember from 'ember';


export default Ember.Route.extend({
  model () {
    const store = this.get('store');
    return store.query('blog.post', { size: 10 });
  }
});

What I'm do is make a pagination mechanism for my blog by replacing the model with the data from the links specified in the links property.

How do I access this "links" property?


Versions

Upvotes: 2

Views: 594

Answers (1)

akst
akst

Reputation: 956

Solution

I ended up extending the serialiser and inserting the links object in the meta object after record array normalization.

// pods:    app/application/serialiser.js
// vanilla: app/serialisers/application.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  /**
   * will attach links to the meta object
   */
  normalizeArrayResponse (...args) {
    const normalized = this._super(...args);
    //
    // since the meta object is optional, it's
    // best to verify if it's null/undefined
    //
    if (normalized.meta == null) {
      normalized.meta = {};
    }
    normalized.meta.links = normalized.links;
    return normalized;
  }
});

So in my route I can access the links the object like so

import Ember from 'ember';

export default Ember.Route.extend({
  model (params) {
    const store = this.get('store');
    return store.query('blog.post', params).then(posts => {
      //
      // access the links object like so.
      //
      const links = posts.get('meta.links');
      return Ember.Object.create({ links, posts })
    });
  }
});

Caveats

This isn't the best solution as it could possibly override any property called links in the meta object.

One way to overcome this is to use a symbol as the fields name, as symbols are unique so you can be certain you won't override any exiting names in the objects namespace. But I haven't tried this and it probably won't work all that well on older browsers and I'm not sure how ember's get method interacts with symbols.

Upvotes: 1

Related Questions