Ember computed 属性 用于从 hasMany 关系中检索一条记录?

Ember computed property for retrieving one record out of a hasMany relationship?

这是我的情况,经过简化:

// model/price-source.js

export default DS.Model.extend({
  price: DS.attr('number'),
  product: DS.belongsTo('product')
)};

// model/product.js

export default DS.Model.extend({
  priceSources: DS.hasMany('price-source')
)};

在我的产品模板中,我希望能够简单地引用价格最低的来源,如下所示:

// templates/products.hbs

{{#each model as |product|}}
<span>{{product.cheapestSource.price}} €</span>
{{/each}}

我将如何设置最便宜的资源计算 属性?我想我必须做这样的事情:

// model/product.js

  cheapestSource: Ember.computed('priceSources', function() {
    let sources = this.get('priceSources');
    let cheapest = sources.get('firstObject');

    // iterate over sources and set cheapest to whichever has the lowest price

    return cheapest;
  })

问题是,我不知道如何遍历 hasMany 关系(除了使用 handlebars {{#each}} 助手),以及计算的 属性 是否可以由单个Ember 来自另一个模型的数据记录。 sources.@each 是否以某种方式参与其中,如果是,如何参与?

感谢任何帮助和想法,谢谢。

您可以在需要使用 cheapestSource 的控制器上执行此操作。

   cheapestSource: Ember.computed('priceSources', function() {
        let sources = this.get('priceSources');
        let cheapest = sources.get('firstObject');   
        let array = sources.mapBy("price");
        let min = array.reduce(function(a, b, i, array) {return Math.min(a,b)});
        sources.forEach(function(source){
          if (source.get("price") == min){
            cheapest = source;
          } 
       });
    return cheapest;
    })

模型有点难以实现您想要的,这就是为什么使用一个计算模板并在渲染计算模板后成为您需要的对象的原因之一。

cheapestSource: Ember.computed('priceSources', function() {
        let product = this;
        this.get('priceSources').then((sources)=>{
        let array = sources.mapBy("price");
        if(array.length>0){
        let min = array.reduce(function(a, b, i, array) {return Math.min(a,b)});
        sources.forEach(function(source){
          if (source.get("price") == min){
            product.set("cheapestSource", source);
          } 
       });
      }
    });
  })

当我遇到这样的问题时,我在 Rails 和 return 上使用活动模型适配器,例如 cheapestSourcePrice 作为我自定义序列化程序中产品的一部分,然后在 Ember 产品模型中添加cheapestSourcePrice 和模板 {{product.cheapestSourcePrice}} 你不t want ember to do heavy lifting like this but if you don控制服务器然后像这样做。在将 source 设置为 cheapesetSource computed 之后的另一件事是在刷新之前不再存在。如果你需要它来保持计算,你必须在模型上再添加一个 属性 然后将他设置为示例

最便宜的来源 2:DS.attr()

这将允许它成为一个对象

product.set("cheapestSource2", 来源);

然后在模板中 {{product.cheapestSource}}{{product.cheapestSource2.price}}

首先 属性 你调用的是那里所以调用计算。

我通过将 priceSources 排序为计算的 属性 sortedPrices,然后在模板中调用 sortedPrices 的 firstObject 使其工作。将很快用实际解决方案编辑此 post。

测试花了很长时间,因为我没有意识到注释掉 handlebars 块会破坏其中 html 的渲染。自我注意...


编辑:这样做了:

export default DS.Model.extend({
  priceSources: DS.hasMany('price-source'),
  sortProperties: ['price:asc'],
  sortedSources: Ember.computed.sort('priceSources', 'sortProperties')
});

然后在模板中:

<span>{{product.sortedSources.firstObject.price}} €</span>

工作正常,无需大量代码。

如果你有时间也试试这个解决方案。 this.get('priceSources') 它 returns Promise 因此您需要在 then 方法中访问结果并将其包装在 DS.PromiseObject 中以便您可以像访问模板中的普通对象一样访问它。

cheapestSource: Ember.computed('priceSources.@each.price', function() {
        return DS.PromiseObject.create({
            promise: this.get('priceSources').then(sources => {
                let resultObj = {}
                    //sources is normal array you can apply your logic and set resultObj
                return resultObj;
            })
        });
    })