Ember中的嵌套后端资源

时间:2019-02-23 13:25:50

标签: ember.js ember-data

这个问题可能是重复的,但我还没有找到答案。

我有一个提供类似URI的Rails API:

/locations/1/visits

在Ember,我有一条这样的路线:

Router.map(function() {
  this.route('location', { path: '/locations/:location_id' }, function() {
    this.route('visits' , { path: 'visits' });
 });
});

..以及类似的模型:

export default DS.Model.extend({
  name:           DS.attr(),
  visits:         DS.hasMany('visit', { nested: true }),
});

当我在浏览器中点击 / locations / 1 / visit 时,我希望Ember同样会在后端点击 / locations / 1 / visits 。而是尝试 / locations / 1 (无访问)。

有什么想法可以说服Ember正确嵌套该关联?

谢谢!

2 个答案:

答案 0 :(得分:1)

我最终放弃了嵌套路由,转而采用了扁平的“模拟”嵌套方案,但借用了@NullVoxPopuli的(谢谢!)适配器技术:

Router.map(function() {
  this.route('visits',   { path: 'locations/:location_id/visits' });
  this.route('visit',    { path: 'locations/:location_id/visits/:id' });
  this.route('checkout', { path: 'locations/:location_id/visits/:id/checkout'} );
});

...然后在/routes/visits.js中:

export default Route.extend({
  model(params) {
    let locationId = params.location_id;
    this.set('locationId', locationId);
    this.store.adapterFor('visit').set('namespace', '/locations/' + locationId);
    let visitsForLocation = this.store.findAll('visit');

    return visitsForLocation;
  }
});

由于解析位置资源对我来说并不重要,因此这种方法似乎可以正常工作。

答案 1 :(得分:0)

前端路由与后端路由不同。

想到前端路由的最简单方法是“嵌套视图”而不是嵌套资源。

因此,关于获取数据(如果您还没有数据),您需要在以下路径上添加一个路由文件:

app / routes / location / visits.js(我想,您也可以ember g route location/visits看看会发生什么事

然后在您的路线上

import Route from '@ember/routing';

export default class LocationVisitsRoute extends Route {
  // this is the route lifecicle hook that actually gets the data
  // more on that here: https://guides.emberjs.com/release/routing/
  async model(params) {
    // this assumes that your location route loads the location resource
    // similar to how we're trying to load the visits resources is this route.
    let locationId = this.modelFor('location').location.id;

    // you could also get the location id from params,
    // but I don't remember the exact path where the id would live.
    console.log(params);

    // this is kind of hacky, and I wouldn't really recommend it, as there may
    // be concurrency issues. but this technique was taken from here:
    // https://discuss.emberjs.com/t/current-way-to-handle-nested-resources/7477/7
    this.store.adapterFor('visit').set('namespace', `/api/locations/${locationId}`);
    let visitsForLocation = await this.store.findAll('visit');

    return { 
      visits: visitsForLocation,
   };

  }
}

然后在访问模板中,您可以

{{#each model.visits as |visit|}}

  <h1>{{visit.name}}</h1>

{{/each}}

或者,如果您使用的是{ json:api },则只需指定links属性,事情就应该“正常”:How to use Ember Data with Nested Resources

因此,总而言之,如果您使用的是{ json:api },则配置有效负载以告知客户端资源/关系实际上是最好的方法。