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

时间:2021-12-09 07:55:25

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:

我有一个'has-many'帮助器(感谢@GJK在一个ember组件模板中的帮助,如何使用'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

佣工/有-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?

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


EDIT 1 These are the models (slightly stripped down, but with the key fields):

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

models/order-notification.js

机型/订单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

车型/ 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

型号/通信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). 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.

通过进入每个并将第四个参数传递给has-any帮助器(未使用),所有的承诺都得到了解决 - 我遇到的问题是

工作! 多次出现(因为任何通过多个联系人/通信多次满足。如果#each中有一种方法仅在第一次满足if时显示if块的内容,则此方法可以工作。

1 个解决方案

#1


1  

So I couldn't do this the way I wanted to but GLK got me in the right direction. At the very lowest layer I aliased communicationType.description in the communication model:

所以我不能按照我想要的方式做到这一点,但GLK让我朝着正确的方向前进。在最低层,我在通信模型中使用了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}}

#1


1  

So I couldn't do this the way I wanted to but GLK got me in the right direction. At the very lowest layer I aliased communicationType.description in the communication model:

所以我不能按照我想要的方式做到这一点,但GLK让我朝着正确的方向前进。在最低层,我在通信模型中使用了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}}