如何使用辅助函数强制Ember进入模板中对象的第二级?

时间:2015-07-16 16:00:26

标签: ember.js

我有一个'has-many'帮助器(感谢In an ember component template how can I use 'if' to check for at least one of an array having a property equal to X?中@GJK的帮助),它允许我在模板中检查一个级别的数组,以便在属性上匹配:

helpers/has-many.js

import Ember from 'ember';

// Param[0]: Array to iterate over
// Param[1]: Comparison operator to use, currently supports '===', '>', '<' and nested 'has-any'
// Param[2]: Value to check for
// (Optional) Param[3]: The property of the arrayObject to check, if this is not supplied the element of the array is checked directly

// Returns: True if array has at least one match to value

export function hasAny(params) {
console.log(params);
  var compare = function(a, b, operator) {
    console.log(a + ' ' + b + ' ' + operator);
    if (operator === '===') {
      return a === b;
    }
    if (operator === '>') {
      return a > b;
    }
    if (operator === '<') {
      return a < b;
    }

    return false;
  };

  if (params.length < 3) {
    return false;
  }

  if (params[0] === undefined || params[1] === undefined || params[2] === undefined) {
    return false;
  }

  if (params.length === 3) {
    return params[0].any((item) => compare(item, params[2], params[1]));
  }

  if (params[3] === undefined) {
    return false;
  }

  return params[0].any((item) => compare(item.get(params[3]), params[2],     params[1]));

}

export default Ember.Helper.helper(hasAny);

我现在想为此添加第二级,以便我可以做相同的

notification.account.contacts.Any(c => c.communications.Any(cm => cm.communicationType.description === 'Email'));

我尝试使用以下内容添加到我的代码中:

助手/具有-many.js

import Ember from 'ember';

// Param[0]: Array to iterate over
// Param[1]: Comparison operator to use, currently supports '===', '>', '<' and nested 'has-any'
// Param[2]: Value to check for
// (Optional) Param[3]: The property of the arrayObject to check, if this is not supplied the element of the array is checked directly

// Returns: True if array has at least one match to value

export function hasAny(params) {
console.log(params);
  var compare = function(a, b, operator) {
    console.log(a + ' ' + b + ' ' + operator);
    if (operator === '===') {
      return a === b;
    }
    if (operator === '>') {
      return a > b;
    }
    if (operator === '<') {
      return a < b;
    }
    if (operator.lastIndexOf('has', 0) === 0) {
      var innerParams = operator.split('%');
      console.log(a);
      return hasAny(a, innerParams[1], innerParams[2], b);
    }
    return false;
  };

  if (params.length < 3) {
    return false;
  }

  if (params[0] === undefined || params[1] === undefined || params[2] === undefined) {
    return false;
  }

  if (params.length === 3) {
    return params[0].any((item) => compare(item, params[2], params[1]));
  }

  if (params[3] === undefined) {
    return false;
  }

  return params[0].any((item) => compare(item.get(params[3]), params[2],     params[1]));

}

export default Ember.Helper.helper(hasAny);

然后在模板中我有:

{{#if (has-any notification.account.contacts 'has-any%===%Email' 'communicationType.description' 'communications')}}
  <p>working!</p>
{{/if}}

我遇到的问题是虽然模板知道一旦notification.account.contacts从API解决后再次触发帮助器,但是一旦每个联系人的通信都从API中断了,它就不知道再次出现 - 我怎么能强制模板/助手获得我的下一级承诺?

编辑1 这些是模型(略微剥离,但有关键字段):

模型/订单notification.js

Export default DS.Model.extend({
  orderNotificationType: DS.belongsTo('orderNotificationType', {async: true}),
  orderNotificationDetail: DS.attr('string'),
  sent: DS.attr('boolean'),
  account: DS.belongsTo('account', {async: true}),
});

模型/ account.js

export default DS.Model.extend({
  name: DS.attr('string'),
  accountType: DS.hasMany('accountType', {async: true}),
  contacts: DS.hasMany('contact', {async: true}),
  addresses: DS.hasMany('address', {async: true}),
});

模型/ contact.js

export default DS.Model.extend({
  title: DS.attr('string'),
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  accounts: DS.hasMany('account', {async: true}),
  communications: DS.hasMany('communication', {async: true})
});

模型/ communication.js

export default DS.Model.extend({
  value: DS.attr('string'),
  communicationType: DS.belongsTo('communicationType', {async: true}),
  contact: DS.belongsTo('contact', {async: true})
});

模型/通信type.js

export default DS.Model.extend({
  description: DS.attr('string'),
  communications: DS.hasMany('communication', {async: true})
});

编辑2

我有一些近乎工作的东西:

{{#each notification.account.contacts as |contact index|}}
  {{#each contact.communications as |communication id|}}
    {{#if (has-any contact.communications '===' 'Email' 'communicationType.description' communication.communicationType.description)}}
    <p>Working!</p>
    {{/if}}
  {{/each}}
{{/each}}

通过进入每个并将第四个参数传递给has-any帮助器(未使用),所有的promise都得到了解决 - 我遇到的问题是<p>Working!</p>多次出现(因为任何通过多个联系人/通信多次满足。如果#each中有一种方法只在第一次满足if时才显示if块的内容,则此方法可以工作。

1 个答案:

答案 0 :(得分:1)

所以我不能按照我想要的方式做到这一点,但GLK让我朝着正确的方向前进。在最低层,我在通信模型中使用了communicationType.description:

communicationTypeDescription: Ember.computed.alias('communicationType.description')

然后我在下一级别的房产中观察到

communicationsAvailable: function() {
  var commsAvailable = [];
  this.get('communications').forEach(function(comm) {
    commsAvailable.push(comm.get('communicationType.description'));
  });
  return commsAvailable.filter(function(value, index, ca) {
    return ca.indexOf(value) === index;
  });
}.property('communications.@each.communicationTypeDescription')

然后我在我的帐户模型中观察到下一层的可观察性(你可以重复这一点,无论你需要多深):

communicationsAvailable: function() {
  var commsAvailable = [];
  this.get('contacts').forEach(function(contact) {
    commsAvailable.push.apply(commsAvailable, contact.get('communicationsAvailable'));
  });
  return commsAvailable.filter(function(value, index, ca) {
    return ca.indexOf(value) === index;
  });
}.property('contacts.@each.communicationsAvailable')

请注意push.apply的细微差别。

最后,我在我的模板中以3个参数形式使用了我的has-many函数:

{{#if (has-any notification.account.communicationsAvailable '===' 'Email')}}
  <p>Working!</p>
{{/if}}