【问题标题】:Decorating data from related model in Ember.js在 Ember.js 中装饰来自相关模型的数据
【发布时间】:2015-02-18 03:45:48
【问题描述】:

我有一个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 路由中,我将模型设置为 Property,然后在模板中,我想输出与 Property 相关的 PricingSummary 的列表,如下所示:

{{#each pricingSummary in pricingSummaries}}

{{render 'summaryRow' pricingSummary}}

{{/each}}

这行得通,我可以在summaryRow 模板中输出每个特定PricingSummary 的属性,例如它的startDateendDate。但我在这里真正想做的是修改/格式化startDate 并输出这个格式化的版本。基本上我想我现在想要一个控制器,但我不知道如何将控制器与正在输出的特定定价摘要模型联系起来。

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

请帮忙!

【问题讨论】:

    标签: ember.js ember-data


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 感谢您提供众多选择。我宁愿在我认为的控制器中做这种事情,而不是模型本身,并且我能够让控制器与我正在渲染的模板同步。但我在那里遇到问题......在这里发布了一个后续问题:stackoverflow.com/questions/28569439/…
    • 无论将计算属性放在模型、控制器还是组件中,语法都是完全相同的。属性路径可能不同,但实现是相同的。你的控制器应该基本上看起来像上面的组件。
    • 我也回答了你的其他问题。
    • 感谢您对这两个问题的回答!你帮了大忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-02
    • 2016-11-28
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    相关资源
    最近更新 更多