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

在Ember.js中装饰来自相关模型的数据,ember.js,ember-data,Ember.js,Ember Data,我有一个属性模型和一个定价汇总模型,它们相互关联,如下所示: 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('pricingSummar

我有一个属性模型和一个定价汇总模型,它们相互关联,如下所示:

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})
});
在属性路由中,我将模型设置为属性,然后在模板中,我希望输出与该属性相关的PricingSummary列表,如下所示:

{{#each pricingSummary in pricingSummaries}}

{{render 'summaryRow' pricingSummary}}

{{/each}}
这是可行的,我能够在summaryRow模板中输出每个特定PricingSummary的属性,比如它的startDate和endDate。但我真正想做的是修改/格式化startDate并输出这个格式化版本。基本上,我想我现在需要一个控制器,但我不知道如何将控制器与输出的特定定价汇总模型联系起来

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


请帮忙

实现这一点有几种方法,而且都相对简单

相对于实际装饰模型而言,最简单的方法是在模型本身上创建计算属性。有些人不喜欢这样,因为他们认为模型应该很瘦,装饰师应该在控制器/组件中,但这完全取决于你的喜好。你可以这样做:

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模式,这样您就可以使用双向绑定,它会将值封送到set上的日期,或get上的字符串。在下面的示例中,我使用moment.js解析/格式化:

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属性,但这实际上与使用render而不必使用自定义视图相同

例如,如果您正在使用更多属性,或者在“定价摘要”行上执行某些操作来删除它,我的首选是使用组件:

{{#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();
    }
  }
});
以及您的组件:

{{#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}}。

感谢您提供了大量选项。我宁愿在控制器中做这类事情,而不是模型本身,我能够让控制器与我正在渲染的模板同步。但我在那里有问题。。。在这里发布了一个后续问题:无论您是将computed属性放在模型、控制器还是组件中,语法都是完全相同的。属性路径可能不同,但实现是相同的。你的控制器应该基本上像上面的组件。我也回答了你的其他问题。谢谢你对这两个问题的回答!你帮了我很大的忙!