排序后模板不会从模型对象渲染

时间:2016-09-30 09:44:21

标签: ember.js promise

我正在使用'type'键对从Ember-Data查询的对象数组进行排序,然后在要呈现的Ember.Route的{​​{3}}方法中返回它们。

应用程序/路由/ test.js

export default Ember.Route.extend({
  model() {
    let obj = Ember.Object.create({a: [], b: [], c: []});
    this.get('store').findAll('obj').then(function(unsorted){
      unsorted.forEach(function(item) {// sort per type
        obj.get(item.get('type')).addObject(item);
      });
      return obj;
    });
  }
});

Ember-Data查询返回的数组(承诺)如下所示(所有对象都有Ember内部属性)

[
  {
    _id: '1',
    type: 'a',
    properties: {...}
  },
  {
    ...
  },
  {
    _id: '15',
    type: 'b',
    properties: {...}
  }
]

对象按“type”-key排序的新对象看起来像这样

{
  a: [{
      _id: '1',
      type: 'a',
      properties: {...}
    },
    ...
  ],
  b: [
    ... ,
    {
      _id: '15',
      type: 'b',
      properties: {...}
    },
  c: [...]
};

应用程序/路由/ test.hbs

<h2>Test</h2>
<h3>Type a</h3>
{{#each model.a as |source|}}
  <div>
    {{source.properties.prop1}}
  </div>
{{/each}}

模板不会渲染循环遍历数组的部分,Ember-inspector插件也不会列出路径“自有属性”下的Model属性(“View tree”中的右侧面板 - 模式)。

然而,当返回一个POJO(字面上用代码中的键的字符粘贴对象)时,一切都按预期运行。
我怀疑这与Ember-data返回的对象的内部(Ember-)属性有关(我已经读过关于对象的所有者等)但我似乎无法弄明白...... < / p>

2 个答案:

答案 0 :(得分:1)

@Pavol的答案解决了基本问题,但是return this.store...then(...) 可以正常工作,因为这是promises的工作方式。阅读the documentation

所以这会奏效:

model() {
  let obj = Ember.Object.create({a: [], b: [], c: []});
  return this.get('store').findAll('obj').then(function(unsorted){
    unsorted.forEach(function(item) {// sort per type
      obj.get(item.get('type')).addObject(item);
    });
    return obj;
  });
}

.then(onFulfilled)返回一个新的promise,它将使用onFulfilled - 回调的返回值来解析。如果您已经拥有承诺并且只能与回调式代码进行互操作,则使用new Promise(...)创建新承诺总是毫无用处。

答案 1 :(得分:-1)

您在model()挂钩中缺少return语句:

export default Ember.Route.extend({
  model() {
    let obj = Ember.Object.create({a: [], b: [], c: []});
    this.get('store').findAll('obj').then(function(unsorted){
      unsorted.forEach(function(item) {// sort per type
        obj.get(item.get('type')).addObject(item);
      });
      return obj;
    });
    // no return value before, findAll() returns promise, thus model() returns undefined
  }
});

但是,添加return this.store...无法解决您的情况,因为您在解决了承诺后更新了不同的对象(then()函数)。 我建议将它包装在一个promise中,然后根据你的排序逻辑解析它传递一个修改过的对象。 注意:我没有考虑在这个阶段排序是否有意义并且是'Ember-way'。排序通常通过控制器/组件级别的计算属性进行。

export default Ember.Route.extend({
  model() {

    return new Ember.RSVP.Promise((resolve)=>{
       let obj = Ember.Object.create({a: [], b: [], c: []});
       this.get('store').findAll('obj').then(function(unsorted){
        unsorted.forEach(function(item) {// sort per type
          obj.get(item.get('type')).addObject(item);
        });
        resolve(obj);
      });
    });

  }
});

更新:当然this.store()会返回一个有效的承诺(我在代码片段中指出但后来解释不正确),所以你不必包装它,抱歉让人感到困惑!我还没有意识到,传递给then()的回调的返回值会自动在一个承诺内部传递,尽管我每天都使用promise chaining和this。对我感到羞耻!感谢@Lux将其放在正确的位置。