简体   繁体   English

如果所有条件都匹配foreach

[英]If all conditions matches inside foreach

I have this type of html: 我有这种类型的HTML:

<p id="username_input" data-priority=""> 
    <label for="username">Username</label>
    <input type="text" class="input-text um-field " name="username" id="username" placeholder="" value="" required="required" data-label="Username">
</p>

<p id="firstname_input" data-priority=""> 
     <label for="firstname">First Name</label>
     <input type="text" class="input-text um-field " name="firstname" id="firstname" placeholder="" value="" required="required" data-label="FirstName">
</p>
<p class="form-row " id="radio_SXsPOwVSD_input"> 
   <input type="radio" class="input-radio um-field" value="Male" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_male">Male 
   <input type="radio" class="input-radio um-field" value="Female" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_Female">Female 
</p>

applyConditions array contains input , condition and value indexes. applyConditions数组包含inputconditionvalue索引。 Could be any inputs and also many conditions. 可以是任何输入,也可以是许多条件。 Suppose, 假设,

input = username
condition = 0 (is)
value = abc

input = firstname
condition = 1 (is not)
value = pqr

I need to do something(show/hide checkbox) if 如果,我需要做一些事情(显示/隐藏复选框)

username is abc and firstname isnot pqr

from the frontend. 从前端。 But could be input radio_sXsPOwVSD, condition 1 and value Male. 但可以输入radio_sXsPOwVSD,条件1和值Male。

then, 然后,

applyConditions.forEach( function( item ) {

  if(item.condition == 0) {
    jQuery("#"+ item.input+"_input").on('change', ( function(  avalue ) {

        return function(e) {                
          if( e.target.value == avalue ) {
                //show checkbox
          }
          else {
                //hide checkbox
          }
        };
    })(item.value));
  }
  else if( item.condition == 1 ) {
        jQuery("#"+ item.input+"_input").on('change', ( function(  avalue ) {

        return function(e) {                
          if( e.target.value != avalue ) {
                //show checkbox
          }
          else {
           //hide checkbox
          }
        };
     })(item.value));
 }

});

However, this seems to be OR, if any matches, but I need all matches. 但是,这似乎是OR,如果有任何匹配,但我需要所有匹配。 I could count the matches and compare with array length, but with onChange count on same field seems to increase/decrease multiple times. 我可以计算匹配并与数组长度进行比较,但是同一场上的onChange计数似乎会多次增加/减少。 What could be the solution? 可能是什么解决方案? I am stuck on this for a while. 我被困在这一段时间了。

applyConditions = 
[
  {"input":"username","condition":"0","value":"abc"}, 
  {"input":"firstname","condition":"1","value":"pqr"}
];

could also be {"input":"radio_SXsPOwVSD","condition":"0","value":"Male"}, 也可以是{"input":"radio_SXsPOwVSD","condition":"0","value":"Male"},

Compare if ($(ele).val() == item.value) equals item.condition 比较if ($(ele).val() == item.value) equals item.condition

to determine whether it matches the condition. 确定它是否符合条件。

The following version now works on radio buttons and checkbox . 以下版本现在适用于radio按钮和checkbox

Well, I finally found that there're name attr on every input. 好吧,我终于发现每个输入上都有名字attr

 var applyConditions = [ { 'input': 'username', 'condition': 0, 'value': 'abc' }, { 'input': 'firstname', 'condition': 1, 'value': 'pqr' }, { "input": "radio_SXsPOwVSD", "condition": 0, "value":"Male" }, { "input": "check_box_XmNoe", "condition": 0, "value": "Apple" } ] applyConditions.forEach(function(condition) { var targetInput = $('input[name='+condition.input+']'); targetInput.on('change',function(){ var results = $.map(applyConditions,(item, index)=>{ var targetInput = $('input[name='+item.input+']'); var type = targetInput.get(0).type; var check = false; if(type == "radio" || type == "checkbox"){ var input = targetInput.get().find(x=>$(x).is(":checked") && $(x).val() == item.value) if (input) { check = input.value == item.value != item.condition; } else{ // since 0 means equal, if there's no any radio button or checkbox is checked, check = false check = item.condition ? true : false; } } else{ check = (targetInput.val() == item.value) != item.condition; } if(check){ // matches } else{ // not matches } return check; }) console.log(...results); }) }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p id="username_input" data-priority=""> <label for="username">Username</label> <input type="text" class="input-text um-field" name="username" id="username" placeholder="" value="" required="required" data-label="Username"> ( ==abc ) </p> <p id="email_input" data-priority=""> <label for="username">Username</label> <input type="text" class="input-text um-field" name="email" id="email" placeholder="" value="" required="required" data-label="Email"> ( no condition ) </p> <p id="firstname_input" data-priority=""> <label for="firstname">First Name</label> <input type="text" class="input-text um-field" name="firstname" id="firstname" placeholder="" value="" required="required" data-label="FirstName"> ( !=pqr ) </p> <p class="form-row" id="radio_SXsPOwVSD_input"> <input type="radio" class="input-radio um-field" value="Male" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_male">Male <input type="radio" class="input-radio um-field" value="Female" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_Female">Female ( Male should be checked ) </p> <p id="check_box_XmNoe_input"> <label class="checkbox data-label=">Checkbox</label> <input type="checkbox" class="input-checkbox um-field" name="check_box_XmNoe" id="check_box_XmNoe_Apple" value="Apple"> Apple <input type="checkbox" class="input-checkbox um-field" name="check_box_XmNoe" id="check_box_XmNoe_Orange" value="Orange"> Orange ( Apple should be checked ) </p> 

This is just an alternative algorithm. 这只是一种替代算法。

 var applyConditions = [ { "input": "username", "condition": "0", "value": "abc", }, { "input": "firstname", "condition": "1", "value": "pqr", }, { "input": "radio_SXsPOwVSD", "condition": "0", "value": "Male" }, ]; var totalConditions = applyConditions.length, conditionFulfilled = 0; function compare($element, rule) { if ($element.length > 1) $element = $element.filter(':checked'); //radio return ($element.val() == rule.value) == (rule.condition == "0"); } function setOK() { if (conditionFulfilled == totalConditions) $('#iresult').html('OK'); else $('#iresult').html('Completed('+conditionFulfilled+'/'+totalConditions+')'); } applyConditions.forEach(function(rule) { var $element = $('[name=' + rule.input + ']'); var isConditionTrue = compare($element, rule); if (isConditionTrue) conditionFulfilled++; $element.change(function() { var updatedIsConditionTrue = compare($element, rule); if (isConditionTrue != updatedIsConditionTrue) { if (updatedIsConditionTrue) conditionFulfilled++; else conditionFulfilled--; isConditionTrue = updatedIsConditionTrue; setOK(); } }); }); setOK(); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p id="username_input" data-priority=""> <label for="username">Username</label> <input type="text" class="input-text um-field " name="username" id="username" placeholder="value = abc" value="" required="required" data-label="Username"> </p> <p id="firstname_input" data-priority=""> <label for="firstname">First Name</label> <input type="text" class="input-text um-field " name="firstname" id="firstname" placeholder="value != pqr" value="" required="required" data-label="FirstName"> </p> <p class="form-row " id="radio_SXsPOwVSD_input"> <input type="radio" class="input-radio um-field" value="Male" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_male">Male <input type="radio" class="input-radio um-field" value="Female" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_Female">Female </p> <div>Result: <b id="iresult">Not OK</b></div> 

Removed the Array and used the data attribute instead. 删除了Array并使用了data属性。

 $(document).ready(function(){ $('.validator').delegate('input', 'change', function(event){ event.stopPropagation(); var condition = $(this).closest('.validator').data('condition'); var valueToCompare = $(this).closest('.validator').data('value'); var result = ""; if(condition == "1"){ result = $(this).val().trim() == valueToCompare ? "Condition Satisfied" : "Condition Not Satisfied"; }else{ result = $(this).val().trim() != valueToCompare ? "Condition Satisfied" : "Condition Not Satisfied"; } console.log(result) }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="validator" data-condition="1" data-value="Rony"> <label for="username">First Name</label> <input type="text" > </div> <div class="validator" data-condition="0" data-value="White"> <label for="username">Last name</label> <input type="text" > </div> <div class="validator" data-condition="1" data-value="Male"> <input type="radio" name="gender" value="Male">Male <input type="radio" name="gender" value="Female">Female </div> <div class="validator" data-condition="0" data-value="Banana"> <input type="radio" name="fruit" value="Apple">Apple <input type="radio" name="fruit" value="Banana">Banana </div> 

To test that every one of a set of conditions is true use Array.prototype.every . 要测试一组条件中的一个都是真的,请使用Array.prototype.every

This solution has a function, setRules , which accepts a set of rules in the above format and returns an object with an onChange property to add listeners. 此解决方案有一个函数setRules ,它接受上述格式的一组规则,并返回一个带有onChange属性的对象来添加侦听器。 These listeners are triggered when any of the values changes and are passed the new boolean value. 当任何值更改并传递新的布尔值时,将触发这些侦听器。 It would not be hard to keep a current value so that this only fires when it switches from true to false or vice-versa. 保持当前值并不难,只有当它从true切换为false或反之时才会触发。

You can use it like this: 你可以像这样使用它:

const ruleHandler = addRules(applyConditions);
ruleHandler.onChange(function(newValue) { /* do something */ }

(or simply chain these together like below.) (或简单地将这些链接在一起,如下所示。)

This also makes it easy to add new conditions, as they are simple functions that accept the current value and the entire rule (enhanced with a jQuery reference to the element.) You can add a condition like this: 这也使得添加新条件变得容易,因为它们是接受当前值和整个规则的简单函数(通过对元素的jQuery引用增强。)您可以添加如下条件:

'2': function(val, rule) {return val.length >= rule.minLength;}

And use it like this: 并像这样使用它:

{input: "lastname", condition: "2", minLength: "4"},

This also points out that you could use arbitrary names for these conditions, rather than "0" and "1" . 这也指出您可以为这些条件使用任意名称,而不是"0""1" Perhaps they could be eq , not_eq , and if you use that last one, minLength . 也许他们可能是eqnot_eq ,如果你使用最后一个, minLength

Most of this is reasonably simple. 其中大部分都相当简单。 The only part that I think needs explanation is this: 我认为需要解释的唯一部分是:

var newVal = rules.every(function(rule) {
  var $elt = (rule.$elt.length > 1) ? rule.$elt.filter(':checked') : rule.$elt;
  return (conds[rule.condition] || function() {return true;})($elt.val(), rule);
})

Note first that we start by calling every on our rules. 首先请注意,我们首先调用every规则。

In the second line we let radio buttons be represented by the :checked element and others by the only element in the $elt object. 在第二行中,我们让单选按钮由:checked元素表示,其他按钮由$elt对象中的唯一元素表示。

The third line is the heart of this code: it finds the correct condition function by looking it up, or if it's not found, chooses a function that simply returns true. 第三行是此代码的核心:它通过查找找到正确的条件函数,或者如果找不到它,则选择一个简单返回true的函数。 Then it calls this function with the value of the element and the rule itself. 然后它使用元素的值和规则本身调用此函数。

 var setRules = function(rules) { var listeners = []; var conds = { '0': function(val, rule) {return val === rule.value;}, '1': function(val, rule) {return val !== rule.value;}, } var test = function() { var newVal = rules.every(function(rule) { var $elt = (rule.$elt.length > 1) ? rule.$elt.filter(':checked') : rule.$elt; return (conds[rule.condition] || function() {return true;})($elt.val(), rule); }) listeners.forEach(listener => listener(newVal)); } rules.forEach(function(rule) { rule.$elt = $('[name=' + rule.input + ']').change(test); }); return { onChange: function(listener) { listeners.push(listener); test(); } }; } var applyConditions = [ {input: "username", condition: "0", value: "abc"}, {input: "firstname", condition: "1", value: "pqr"}, {input: "radio_SXsPOwVSD", condition: "0", value: "Male"} ]; const $results = $('#result'); setRules(applyConditions).onChange(function(newVal) { $results.html(newVal ? 'OK' : 'Not OK'); }) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p id="username_input" data-priority=""> <label for="username">Username</label> <input type="text" name="username" id="username" value="abc"> </p> <p id="firstname_input" data-priority=""> <label for="firstname">First Name</label> <input type="text" name="firstname" id="firstname" value="pqr"> </p> <p id="radio_SXsPOwVSD_input"> <input type="radio" value="Male" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_male" checked>Male <input type="radio" value="Female" name="radio_SXsPOwVSD" id="radio_SXsPOwVSD_Female">Female </p> <div>Result: <b id="result">Not OK</b></div> 

Also note that this would be cleaner and more readable if you were using ES6: 另请注意,如果您使用ES6,这将更清晰,更易读:

const setRules = (rules) => {
  const listeners = [];
  const conds = {
    '0': (val, rule) => val === rule.value,
    '1': (val, rule) => val !== rule.value
  }
  const test = () => {
    var newVal = rules.every(function(rule) {
      var $elt = (rule.$elt.length > 1) ? rule.$elt.filter(':checked') : rule.$elt;
      return (conds[rule.condition] || (() => true))($elt.val(), rule);
    })
    listeners.forEach(listener => listener(newVal));
  }
  rules.forEach((rule) => {
    rule.$elt = $('[name=' + rule.input + ']').change(test);
  });
  return {
    onChange: (listener) => {
      listeners.push(listener); 
      test(); 
    }
  };
}   

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

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