0

这是我的情况,简化:

// 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}} €&lt;/span>
{{/each}}

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

// 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 关系(除了使用把手 {{#each}} 帮助器),以及计算属性是否甚至可以包含来自另一个模型的单个 Ember 数据记录。sources.@each 是否以某种方式参与其中,如果是这样,如何?

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

4

3 回答 3

1

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

测试需要很长时间,因为我没有意识到注释掉车把块会破坏其中的 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}} €&lt;/span>

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

于 2017-02-18T17:53:56.353 回答
0

您可以在需要使用最便宜来源的控制器上执行此操作。

   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 上使用活动模型适配器并在我的自定义序列化程序中返回例如最便宜的SourcePrice 作为产品的一部分,然后在 Ember 产品模型中只需添加最便宜的SourcePrice 和模板 {{product.cheapestSourcePrice}} 你不t want ember to do heavy lifting like this but if you don控制服务器然后这样做。在将源设置为cheesesetSource 计算之后的另一件事就是刷新。如果您需要它保持计算状态,您必须在模型上再添加一个属性,然后设置他 insted 示例

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

这将允许它成为一个对象

product.set("cheapestSource2", source);

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

您调用的第一个属性在那里,因此调用了计算。

于 2017-02-18T15:10:41.177 回答
0

如果你有时间也试试这个解决方案。this.get('priceSources')它返回 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;
            })
        });
    })
于 2017-02-18T18:06:39.750 回答