【问题标题】:ember model rendering strange behaviuorember 模型呈现奇怪的行为
【发布时间】:2015-06-17 15:32:29
【问题描述】:

在尝试使用 ember 和 ember-localforage-adapter 时,我注意到一个奇怪的行为。

ember.debug.js:4888DEBUG: Ember      : 1.12.0
ember.debug.js:4888DEBUG: Ember Data : 1.0.0-beta.18
ember.debug.js:4888DEBUG: jQuery     : 1.11.3

我有三个模型:

/app/models/ledger.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),

  purchases: DS.hasMany('purchase', {async: true}),
  players: DS.hasMany('player', {async: true}),
});

/app/models/purchase.js

import DS from 'ember-data';

export default DS.Model.extend({
  name: DS.attr('string'),
  amount: DS.attr('number'),

  ledger: DS.belongsTo('ledger', {async: true}),
  player: DS.belongsTo('player', {async: true})
});

/app/models/player.js

import DS from 'ember-data';

export default DS.Model.extend({
  name: DS.attr('string'),
  balance: DS.attr('number'),

  ledger: DS.belongsTo('ledger',{ async: true }),
  purchases: DS.hasMany('purchase', {async: true}),
});

还有一条简单的路线:

/app/routes/purchase.js

import Ember from 'ember';

export default Ember.Route.extend({
  model: function(params) {
    return this.store.find('purchase', params.purchase_id);
  }
});

我的实验模板是

/app/templates/purchase.hbs

name: {{model.name}}
<br>
amount: {{model.amount}}
<br>
player: {{model.player.name}}

它可以向我显示所有调用的属性。但是,如果我添加另一行,例如

name: {{model.name}}
<br>
amount: {{model.amount}}
<br>
player: {{model.player.name}}
<br>
ledger: {{model.player.ledger.title}}

它只显示玩家的名字,从不显示账本标题。应如何在存储中加载请求的记录以使其在我的模板中可用?

【问题讨论】:

  • 你会显示服务器对所有记录请求的响应吗?
  • 如果我有机会看到 ember-data 如何与持久层交互,我会明白很多。使用 ember-localforage-adapter 之类的类似 localStorage 的库使我无法理解该迭代。事实上,如果我不碰一下啊,我会为此目的构建一个后端 api。还是谢谢

标签: ember.js


【解决方案1】:

看完this我把属性payer添加到购买模型中:

  payer: function(){
    return DS.PromiseObject.create({
      promise: this.get( 'player' )
    });
  }.property('')

在模板中使用而不是player:

<h3>show purchase</h3>

model.name: <strong>{{model.name}}</strong>
<br>
model.amount: <strong>{{model.amount}}</strong>
<br>
<br>
model.payer.name: <strong>{{model.payer.name}}</strong>
<br>
model.payer.ledger.title: <strong>{{model.payer.ledger.title}}</strong>
<br>
<br>
model.player.name: <strong>{{model.player.name}}</strong>
<br>
model.player.ledger.title: <strong>{{model.player.ledger.title}}</strong>

这种方法与 Artych 建议的方法非常相似,但可能由于我的 Rails 背景,我更喜欢通过模型而不是与路由关联的控制器从任何地方访问关联记录

以下 gif(如果没有看到动画,请下载)显示了两者的行为:

有人可以解释发生了什么吗?为什么model.player.namemodel.plyer.ledger.title出现的时候消失了?考虑到两者都返回 DS.PromiseObject,从模板的角度来看,payerplayer 有什么区别?

【讨论】:

    【解决方案2】:

    你可以尝试在afterModel钩子中解析model.player.ledger

    afterModel: function(model) {
      var controller = this.controllerFor('purchase');
    
      model.get('player').then(function(player) {
        controller.set('player', player);
        return player.get('ledger');
    
      }).then(function(ledger){
        controller.set('playerLedger', ledger);
      }, function(error) {
        console.log("promise is not resolved", error);
      });
    }
    

    在模板中

     {{player.name}} | {{playerLedger.title}}
    

    我想你可以看到为什么model.player.ledger 没有被解析或者它可能是空的。

    player 模型中有错字。应该是:

     //app/models/player.js
     import DS from 'ember-data';
     export default DS.Model.extend({
       // ...
    
       ledger: DS.belongsTo('ledger', { async: true }),
       //not ledger: DS.belongsTo({ async: true }),
    
     });
    

    【讨论】:

    • 感谢 artyc.. 改变但行为相同。其实我也不确定,但是我觉得当等于关联名的时候可以省略模型名。
    • Artych 您的解决方法取得了成功。其实我只需要设置player 并用player.ledger 检索关联分类帐。我会接受你的回答,但我不相信这是加载关联记录的 ember 方式。由于我来自 rails ActiveRecord,我希望(我希望)ember-data 会在需要时执行此操作。也许我错过了一些大事
    • 可能是 ember 无法解析深层嵌套的 promices,所以 {{model.player.ledger.title}} 不起作用,但 {{model.player.name}} 起作用。我不清楚。如果你在商店里已经有player.ledger,(例如你已经解决了player.ledger或者在父路由中找到所有的分类帐),{{model.player.ledger.title}}应该可以工作,没有你的afterModel钩子。
    猜你喜欢
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多