如何强制Ember进入模板中使用辅助函数的对象的第二级? [英] How can I force Ember to get into the second level of an object in a template using a helper function?

查看:204
本文介绍了如何强制Ember进入模板中使用辅助函数的对象的第二级?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很多的帮手(感谢@GJK在在ember组件模板中,如何使用'if'来检查具有相同属性的数组中的至少一个到X?),允许我检查我的模板中的一个数组在属性上的匹配:

  helpers / has-many.js 

从ember导入Ember;

// Param [0]:数组迭代
// Param [1]:使用比较运算符,目前支持'===','>','< ;'和嵌套'has-any'
// Param [2]:检查
的值(可选)Param [3]:要检查的arrayObject的属性,如果不是提供的数组的元素被直接检查

//返回:如果数组至少有一个匹配值为

导出函数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假;
}

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

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

返回参数[0] .any((item)=> compare(item.get(params [3]),params [2],params [1])) ;

}

导出默认值Ember.Helper.helper(hasAny);

我现在要添加第二个级别,以便我可以做相当于

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

我尝试添加以下代码:


$ b $从ember导入Ember; b

helpers / has-many.js

  

// Param [0]:数组迭代
// Param [1]:使用比较运算符,目前支持'===','>','< ;'和嵌套'has-any'
// Param [2]:检查
的值(可选)Param [3]:要检查的arrayObject的属性,如果不是提供的数组的元素被直接检查

//返回:如果数组至少有一个匹配值为

导出函数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);
}
返回false;
};

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

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

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

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

返回参数[0] .any((item)=> compare(item.get(params [3]),params [2],params [1])) ;

}

导出默认值Ember.Helper.helper(hasAny);

然后在模板中我有:

  {{if(has-any notification.account.contacts'has-any%===%Email''communicationType.description''communications')}} 
< p为H.工作<!/ p为H.
{{/ if}}

我遇到的问题是虽然模板知道要点火一旦notify.account.contacts已经从API中解决出来,帮助者再次通知API,那么一旦每个联系人的通信从API中下来,它就不知道再去一次 - 我如何强制模板/帮助者获得我的下一个承诺? / p>




编辑1
这些是模特儿(略有剥离,关键字段):



models / order-notification.js

 导出默认DS.Model.extend({
orderNotificationType:DS.belongsTo('orderNotificationType',{async:true}),
orderNotificationDetail:DS.attr('string'),
:DS.attr('boolean'),
account:DS.belongsTo('account',{async:true}),
});

models / account.js

 导出默认DS.Model.extend({
name:DS.attr('string'),
accountType:DS.hasMany('accountType',{async:true }),
联系人:DS.hasMany('contact',{async:true}),
地址:DS.hasMany('address',{async:true}),
} );

models / contact.js

 导出默认DS.Model.extend({
标题:DS.attr('string'),
firstName:DS.attr('string'),
lastName:DS.attr('string'),
accounts:DS.hasMany('account',{async:true}),
communication:DS.hasMany('communication',{async: true})
});

models / communication.js

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

models / communication-type.js

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






编辑2 / p>

我有几件工作:

  {{each notice.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帮助器(未使用),所有的承诺都被解决 - 我遇到的问题是< ; p> Working!< / p> 多次出现(因为多个联系人/通信多次满足)。如果#each中有一种方法,只有在第一次满足if时才显示if块的内容,那么该方法可以工作。

解决方案

所以我不能这样做,但是GLK让我走向正确的方向。在最底层,我通信模型中的通信类型描述为alias:

  communicationTypeDescription:Ember.computed.alias('communicationType。描述')

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

  communicationAvailable: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



最后,我使用我的has-many功能,它的3个参数我的模板:

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


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:

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

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?


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

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

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

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

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

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


EDIT 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.

解决方案

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:

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.

Finally, I then used my has-many function in it's 3 param form in my template:

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

这篇关于如何强制Ember进入模板中使用辅助函数的对象的第二级?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆