Load data belonging to a parent model with Ember.js

笑着哭i 提交于 2019-12-11 12:43:28

问题


Considering something similar to the example outlined here:

App.Router.map(function() {
  this.resource("posts", function() {
    this.resource("post", { path: "/posts/:post_id" }, function() {
      this.resource("comments", { path: "/comments" });
    });
  });
});

using the DS.RESTAdapter. The Router would load all the posts when I access the PostsRoute with a call to the API URL /posts.

When I then access PostRoute, for example for the post with id=1, it doesn't hit the API again, i.e. it doesn't hit /post/1. It loads the post from the store.

I want then to access CommentsRoute for post with id=1. How do I load the comments?

Should I have sideloaded all the comments in the first place, when I loaded the post list? In this case though, I would need to load all the comments for all the posts. Is it possible to load the comments only when needed, i.e. when I access CommentsRoute?

In this case, how do I actually load the comments from the backend? Specifically, how do I write the CommentsRoute to load the comments from the RESTful API when I access the page that actually displays them?

I guess one needs to have the following:

App.Post = DS.Model.extend({
  comments: DS.hasMany('comment')
});

App.Comment = DS.Model.extend({
  post: DS.belongsTo('post')
});

App.CommentsRoute = Ember.Route.extend({
  model: function() {
    /*
     * How do I inject params.post_id here
     * to make a request to the RESTful API?
     * Which URL would be called?
     * /comments?post_id=ID
     * /post/post_id/comments
     * ...
     */

    // Doesn't work, hits /comments
    return this.store.find('comment', { post_id: params.post_id });
  }
});

Why does

return this.store.find('comment', { post_id: params.post_id });

hit /comments?


回答1:


You just need to declare your CommentsRoute like this:

App.CommentsRoute = Ember.Route.extend({
  model: function() {
    return this.modelFor('post').get('comments');
  }
});

What it does is, it gets the model of the PostRoute and fetches its comments.

Ember-data handles the logic behind it. If comments were sideloaded, it will just return these. Otherwise it will issue a GET request to fetch them.

For this to work, you need to include the links property on a serialized post. The links property needs to include the URL you wish ember-data to use in order to fetch the comments.

E.g. your serialized post may look like this:

{
  "post": {
    "id": 1,
    "title": "Rails is omakase",
    "links": { "comments": "/posts/1/comments" }
  }
}

See DS.RESTAdapter#findHasMany.

The hasMany relationship probably needs to be declared async for this to work properly:

App.Post = DS.Model.extend({
  comments: DS.hasMany('comment', { async: true })
});



回答2:


You can use Ember's sideloaded relationships to make the posts API endpoint also return the relevant comments and Ember will figure it out.

http://emberjs.com/guides/models/the-rest-adapter/#toc_sideloaded-relationships

{
  "post": {
    "id": 1,
    "title": "Node is not omakase",
    "comments": [1, 2, 3]
  },

  "comments": [{
    "id": 1,
    "body": "But is it _lightweight_ omakase?"
  },
  {
    "id": 2,
    "body": "I for one welcome our new omakase overlords"
  },
  {
    "id": 3,
    "body": "Put me on the fast track to a delicious dinner"
  }]
}

You'd then be able to pass the already loaded comments to the comments route.

It may be in the docs but it's quite a specific term! Some of the concepts like that can be a bit tricky to search for.




回答3:


The following forces a call to the backend /comments?post_id=ID

App.CommentsController = Ember.ArrayController.extend({
  needs: 'post'
});

App.CommentsRoute = Ember.Route.extend({
  model: function(params) {
    return this.store.find('comment', { post_id: this.modelFor('post').get('id') });
  }
});


来源:https://stackoverflow.com/questions/23958323/load-data-belonging-to-a-parent-model-with-ember-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!