装饰 Ember.js 中相关模型的数据

Decorating data from related model in Ember.js

我有一个 Property 模型和一个 Pricing Summary 模型,它们相互关联,如下所示:

App.Property = DS.Model.extend({
    totalRoomCount: DS.attr(),
    name: DS.attr(),
    address: DS.attr(),
    city: DS.attr(),
    state: DS.attr(),
    zip: DS.attr(),
    pricingSummaries: DS.hasMany('pricingSummary', {async: true})
});

App.PricingSummary = DS.Model.extend({
    startDate: DS.attr(),
    endDate: DS.attr(),
    days: DS.hasMany('day', {async: true}),
    property: DS.belongsTo('property', {async: true})
});

在我的 属性 路线中,我将模型设置为 Property,然后在模板中,我想输出相关的 PricingSummary 列表那个Property,如下:

{{#each pricingSummary in pricingSummaries}}

{{render 'summaryRow' pricingSummary}}

{{/each}}

这行得通,我能够在 summaryRow 模板中输出每个特定 PricingSummary 的属性,例如它的 startDateendDate,因为例子。但我在这里真正想做的是 modify/format startDate 并输出这个格式化版本。基本上我想此时我需要一个控制器,但我不知道如何将控制器绑定到正在输出的特定定价摘要模型。

我该怎么做?此外,您可以看到 PricingSummary 也与我的 Day 模型有关系,所以我想再做一次,另一个层次。

请帮忙!

有几种方法可以实现这一点,而且都比较简单。

关于实际装饰模型,最简单的方法是在模型本身上创建计算 属性。有些人不喜欢这样,因为他们认为模型应该很瘦,装饰器应该在 controllers/components 中,但这完全取决于您的喜好。你可以这样完成它:

App.YourModel = DS.Model.extend({
  date: attr('date'),
  formattedDate: function() {
    var date = this.get('date');
    return date ? this.get('date').toDateString() : null ; // Use your own format :-)
  }.property('date')
});

或者,我喜欢使用 getter/setter 模式,这样您就可以使用双向绑定,它会将值编组为设置的日期,或编组为获取的字符串。在下面的示例中,我使用 moment.js 到 parse/format:

App.YourModel = DS.Model.extend({
  date: attr('date'),
  dateMarshal: function(key, value) {
    if (arguments.length > 1) {
      var parsed = moment(value);
      this.set('date', parsed.isValid() ? parsed.toDate() : null);
    }
    return this.get('date') ? moment(this.get('date')).format('MM/DD/YYYY') : null ;
  }.property('date'),
});

另一种选择是向 {{#each}} 帮助程序提供 itemController 属性,但这实际上与使用渲染相同,而无需使用自定义视图。

如果您要使用更多属性并且可能对定价摘要行执行一些操作(例如删除它),我的首选是使用一个组件:

{{#each pricingSummary in pricingSummaries}}
  {{pricing-summary-item content=pricingSummary}}
{{/each}}

你的组件:

App.PricingSummaryItem = Ember.Component.extend({
  content: null,
  dateFormatted: function() {
    var formattedDate = this.get('content.date');
    // Format your date
    return formattedDate;
  }.property('content.date')
  actions: {
    'delete': function() {
      this.get('content').deleteRecord();
    },
    markRead: function() {
      this.set('content.isRead', true);
      this.get('content').save();
    }
  }
});

最后,为了解决日期问题而不是装饰问题,我会制作一个绑定助手。同样,此示例使用 moment.js(我也使用 ember-cli,所以请原谅 ES6 语法):

import Ember from 'ember';

export function formatDate(input, options) {
  input = moment(input);
  if (options.hashContexts.fromNow) {
    return input.fromNow();
  } else {
    return input.format(options.hash.format || 'LL');
  }
}

export default Ember.Handlebars.makeBoundHelper(formatDate);

那么您只需在模板中使用 {{format-date yourDateProperty}}