如果 foreach 中的所有条件都匹配

If all conditions matches inside foreach

提问人:micky 提问时间:3/31/2018 最后编辑:micky 更新时间:4/9/2018 访问量:1362

问:

我有这种类型的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数组包含 和 索引。可以是任何输入,也可以是许多条件。假设inputconditionvalue

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

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

如果出现以下情况,我需要做点什么(显示/隐藏复选框)

username is abc and firstname isnot pqr

从前端。但可以输入radio_sXsPOwVSD、条件 1 和值 Male。

然后

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

});

但是,这似乎是 OR,如果有任何匹配,但我需要所有匹配。我可以计算匹配项并与数组长度进行比较,但是在同一字段上使用 onChange 计数似乎会增加/减少多次。解决方案是什么?我被困在上面一段时间了。

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

也可能是{"input":"radio_SXsPOwVSD","condition":"0","value":"Male"},

JavaScript jQuery

评论

0赞 Roemer 3/31/2018
如果您让我们更广泛地了解您在这里尝试做的事情,那将会有所帮助。如果它是对任何字段的更改进行动态表单验证的一种形式,则最好使用带有事件处理程序的 foreach 循环。但我不确定这是否是你想要的。
0赞 Hikarunomemory 3/31/2018
在条件 0 中,选择器在“_input”内,但在条件 1 中它是“_field”?
0赞 micky 3/31/2018
@Hikarunmemory哦,这是两者的输入。我决定以后再改。
0赞 micky 3/31/2018
@Roemer,表单是静态的,但应用条件的条件和字段可能会有所不同。
1赞 Roemer 3/31/2018
这就是我的意思。我会在事件处理程序中做一个完整的测试循环,并将相同的事件处理程序分配给所有元素。原因很容易理解:你不能按照自己的方式做一个“AND”,因为你每次只测试一个元素。您需要一次测试它们。

答:

13赞 Hikarunomemory 3/31/2018 #1

比较是否相等($(ele).val() == item.value)item.condition

以确定它是否与条件匹配。

以下版本现在适用于按钮和 .radiocheckbox

好吧,我终于发现每个输入上都有名字。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>

评论

0赞 Rob 4/3/2018
评论不用于扩展讨论;此对话已移至 Chat
3赞 Munim Munna 4/2/2018 #2

这只是一种替代算法。

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>

3赞 Kuldeep Dubey 4/3/2018 #3

删除了 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>

3赞 Scott Sauyet 4/7/2018 #4

要测试一组条件中的每一个都为真,请使用 Array.prototype.every

此解决方案有一个函数 ,它接受上述格式的一组规则,并返回一个对象,该对象具有用于添加侦听器的属性。当任何值发生更改并传递新的布尔值时,将触发这些侦听器。保留当前值并不难,这样它只在从切换到 时触发,反之亦然。setRulesonChangetruefalse

你可以像这样使用它:

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

(或者简单地将它们链接在一起,如下所示。

这也使得添加新条件变得容易,因为它们是接受当前值和整个规则的简单函数(通过对元素的 jQuery 引用进行增强)。您可以添加如下条件:

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

并像这样使用它:

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

这还指出,您可以对这些条件使用任意名称,而不是 和 。也许它们可能是 , ,如果你使用最后一个,."0""1"eqnot_eqminLength

其中大部分都相当简单。我认为唯一需要解释的部分是:

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

首先要注意的是,我们从调用我们的规则开始。every

在第二行中,我们让单选按钮由元素表示,其他单选按钮由对象中的唯一元素表示。:checked$elt

第三行是这段代码的核心:它通过查找来找到正确的条件函数,或者如果找不到,则选择一个只返回 true 的函数。然后,它使用元素和规则本身的值调用此函数。

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>

另请注意,如果您使用的是 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(); 
    }
  };
}