简体   繁体   English

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

[英]How can I force Ember to get into the second level of an object in a template using a helper function?

I have a 'has-many' helper (thanks to the help of @GJK in 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? ) that allows me to check one level of an array in my template for a match on a property: 我有一个“非常多”的助手(由于在余烬组件模板中的@GJK的帮助, 我如何使用“ if”来检查至少一个具有等于X的属性的数组? )在我的模板中检查数组的一个级别是否与某个属性匹配:

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);

I now want to add a second level to this so that I can do the equivalent of 我现在想在此添加第二个级别,以便可以执行以下操作:

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

I tried adding to my code with the following: 我尝试使用以下代码添加到我的代码中:

helpers/has-many.js 助手/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;
    }
    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);

And then in the template I have: 然后在模板中,我有:

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

The problem I have is although the template knows to fire the helper again once notification.account.contacts has resolved from the API, it doesnt know to go again once each contacts' communications have come down from the API - how can I force the template/helper to get my next level of promises? 我遇到的问题是,尽管从API解析了notify.account.contacts后,模板知道再次触发该助手,但是当每个联系人的通信都从API断开后,它不知道再次执行该操作-我该如何强制该模板/ helper获得我的下一个承诺?


EDIT 1 These are the models (slightly stripped down, but with the key fields): 编辑1这些是模型(略有简化,但有关键字段):

models/order-notification.js models / order-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}),
});

models/account.js models / 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}),
});

models/contact.js 型号/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})
});

models/communication.js 模型/communication.js

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

models/communication-type.js 模型/communication-type.js

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

EDIT 2 编辑2

I've got something nearly working: 我有一些几乎可以工作的东西:

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

By going within the each and passing a fourth parameter to the has-any helper (that is unused), all the promises are resolved - the problem I have is that <p>Working!</p> comes up multiple times (because the any is satisfied multiple times by multiple contacts/communications). 通过遍历每个变量并将第四个参数传递给有任何帮助者(即未使用的),所有的诺言都得以解决-我遇到的问题是<p>Working!</p>多次出现(因为多个联系人/通讯多次满足任何条件)。 This method could work if there is a way within an #each to display the contents of an if block only the first time the if is satisfied. 如果#each内只有一种方法可以在仅满足if的条件下才显示if块的内容,则此方法可以工作。

So I couldn't do this the way I wanted to but GLK got me in the right direction. 因此,我无法按照自己想要的方式进行操作,但是GLK使我朝着正确的方向前进。 At the very lowest layer I aliased communicationType.description in the communication model: 在最底层,我在通信模型中为communicationType.description别名:

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

I then observe that in a property at the next level up 然后,我观察到在更高级别的属性中

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')

I then observe that observable at the next layer up (you could repeat this bit for however deep you need), in my account model: 然后,在我的帐户模型中,我观察到下一层的可观察性(您可以根据需要的深度重复此步骤):

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')

Note the subtle difference here of push.apply . 注意这里push.apply的细微差别。

Finally, I then used my has-many function in it's 3 param form in my template: 最后,然后在模板中以3参数形式使用了has-many函数:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM