How can I validate a group within another group and maintain separate error messages?

不打扰是莪最后的温柔 提交于 2019-12-14 02:52:59

问题


I'm trying to use the 'require_from_group_update' method with jquery validator and have run into a snag I need help with. I working with multiple forms (24 in total) and each has many, many fields. In some instances, I need to validate groups of questions. As long as the groups are exclusive, this works great, but in some instances, for example, I need to have 5 total answers but at least 3 from the last 4 questions.

So that could mean 1 question in the first group is required and 4 from the second or 2 from the first and 3 from the second, etc. In my real form, the forms have between 10 and 20 questions long with different required counts for each.

I created the example with the fields in separate groups but really wanted to see if it was possible to check if 3 of the last 4 questions are answered and that 5 out of the total 8 are also answered. I tried to have all questions in one group and the last 4 in another - but that didn't work. Here I just picked 8 as example - in reality, there can be 10 to 20 total questions with varying requirements for each.

Many thanks in advance - I hope this is clear and concise enough.

Sample code is below - or there's a fiddle as well - jsfiddle.net/43rdworld/qZ6rn/4/

    <!DOCTYPE html>
      <html lang="en">
    <head>
      <title>Online Nomination Form</title>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
            <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.0/jquery.validate.js"></script> 
            <style type="text/css" media="all">
      textarea {margin-left:20px;}
      .wrapper {width: 200px;clear:both;float:left;margin-bottom:10px;}
      div.errorContainer {width:200px;float:left;font-size:9pt;}
            </style>     
    <script>
              $(document).ready(function () {
                $("#theForm").validate({
                  groups: {
                    group1: "sm_Appreciation,sm_Impact,sm_Safety,sm_People,sm_Parents,sm_Goals,sm_Money,sm_Decision",
                    group2: "sm_Parents,sm_Goals,sm_Money,sm_Decision"
                 },
                   rules: {
                     sm_Appreciation: {require_from_group_updated: [2, ".smg1"]},
                     sm_Impact: {require_from_group_updated: [2, ".smg1"]},
                     sm_Safety: {require_from_group_updated: [2, ".smg1"]},
                     sm_People: {require_from_group_updated: [2, ".smg1"]},
                     sm_Parents: {require_from_group_updated: [3, ".smg2"]},
                     sm_Goals: {require_from_group_updated: [3, ".smg2"]},
                     sm_Money: {require_from_group_updated: [3, ".smg2"]},
                     sm_Decision: {require_from_group_updated: [3, ".smg2"]},
        },
              errorPlacement: function(error, element) {
                 if ((element.attr("name") === "sm_Appreciation") || (element.attr("name") === "sm_Impact") || (element.attr("name") === "sm_Safety") || (element.attr("name") === "sm_People")) {
                            error.appendTo("#smError1");
                    } else if ((element.attr("name") === "sm_Parents") || (element.attr("name") === "sm_Goals") || (element.attr("name") === "sm_Money") || (element.attr("name") === "sm_Decision")) {
                            error.appendTo("#smError2");
                    }
          },
        });

        jQuery.validator.addMethod('require_from_group_updated', function (value, element, options) {
            var numberRequired = options[0];
            var selector = options[1];
            var fields = $(selector, element.form);
            var filled_fields = fields.filter(function () {
            // it's more clear to compare with empty string
                return $(this).val() != "";
            });
            var empty_fields = fields.not(filled_fields);
            // we will mark only first empty field as invalid
            if (filled_fields.length < numberRequired && empty_fields[0] == element) {
                return false;
            }
            return true;
            // {0} below is the 0th item in the options field
            }, jQuery.format("* Please fill out at least {0} of these fields."));
        });
    </script>
</head>
    <body>
    <form name="theForm" id="theForm" method="post" action="" autocomplete="off">
        <h4>Answer 5 of the following 8 questions, with at least 3 from questions 4-8</h4>
        <div class="wrapper">
            <label for="sm_Appreciation">1. Question 1</label><br>
            <textarea name="sm_Appreciation" id="sm_Appreciation" class="smg1" rows="3" cols="20" maxlength="200" tabindex="1"></textarea>
        </div>
        <div id="smError1" class="errorContainer"></div>
        <div class="wrapper">
            <label for="sm_Impact">2. Question 2</label><br>
            <textarea name="sm_Impact" id="sm_Impact" class="smg1" rows="3" cols="20" maxlength="200" tabindex="2"></textarea>
        </div>
        <div class="wrapper">
            <label for="sm_Safety">3. Question 3</label><br>
            <textarea name="sm_Safety" id="sm_Safety" class="smg1" rows="3" cols="20" maxlength="200" tabindex="3"></textarea>
        </div>
        <div class="wrapper">
            <label for="sm_People">4. Question 4</label><br>
            <textarea name="sm_People" id="sm_People" class="smg1" rows="3" cols="20" maxlength="200" tabindex="4"></textarea>
        </div>
        <h4 style="clear:both;">Answer at least 3 questions from questions 4 through 8</h4>
        <div class="wrapper">
            <label for="sm_Parents">5. Question 5</label><br>
            <textarea name="sm_Parents" id="sm_Parents" class="smg2" rows="3" cols="20" maxlength="200" tabindex="5"></textarea>
        </div>
        <div id="smError2" class="errorContainer"></div>
        <div class="wrapper">
            <label for="sm_Goals">6. Question 6</label><br>
            <textarea name="sm_Goals" id="sm_Goals" class="smg2" rows="3" cols="20" maxlength="200" tabindex="6"></textarea>
        </div>
        <div class="wrapper">
            <label for="sm_Money">7. Question 7</label><br>
            <textarea name="sm_Money" id="sm_Money" class="smg2" rows="3" cols="20" maxlength="200" tabindex="7"></textarea>
        </div>
        <div class="wrapper">
            <label for="sm_Decision">8. Question 8</label><br>
            <textarea name="sm_Decision" id="sm_Decision" class="smg2" rows="3" cols="20" maxlength="200" tabindex="8"></textarea>
        </div>
        <div style="clear:both;"><input type="submit" value="submit"></div>
    </form>
</body>
    </html>

回答1:


First I updated the plugin to version 1.11.1 and I included the corresponding version of the additional-methods.js file. Version 1.11.1 is where all the bugs were finally fixed in the require_from_group method.

Then I simply created a group within a group. You already have the right idea with your groups option, but that's only used for consolidating the error messages. Since your whole form is one group, you have to apply the require_from_group rule to all fields. Then since you have another unique group within it, you have to again apply the require_from_group rule to only those fields.

rules: {
    sm_Appreciation: {
        require_from_group: [5, ".smg1"]
    },
    sm_Impact: {
        require_from_group: [5, ".smg1"]
    },
    sm_Safety: {
        require_from_group: [5, ".smg1"]
    },
    sm_People: {
       require_from_group: [5, ".smg1"]
    },
    sm_Parents: {
        require_from_group: [5, ".smg1"],
        require_from_group: [3, ".smg2"]
    },
    sm_Goals: {
        require_from_group: [5, ".smg1"],
        require_from_group: [3, ".smg2"]
    },
    sm_Money: {
        require_from_group: [5, ".smg1"],
        require_from_group: [3, ".smg2"]
    },
    sm_Decision: {
        require_from_group: [5, ".smg1"],
        require_from_group: [3, ".smg2"]
    }
},

And finally, you can clean up your errorPlacement by using the class name rather than manually checking against each field name. I also removed the .appendTo() method because it just keeps repeating the error message creating a whole string of the same message over and over.

errorPlacement: function (error, element) {
    // if it's only part of 'smg1' group and not 'smg2' sub-group
    if (element.hasClass("smg1") && !element.hasClass("smg2")) {
        $("#smError1").html(error);
    // else if it's part of 'smg2' sub-group
    } else if (element.hasClass("smg2")) {
        $("#smError2").html(error);
    }
},
groups: {
    group1: "sm_Appreciation,sm_Impact,sm_Safety,sm_People",
    group2: "sm_Parents,sm_Goals,sm_Money,sm_Decision"
}

Working DEMO: http://jsfiddle.net/2xW76/

You'll probably still need to tweak your message placement and your groups option for the exact desired effect, however, my demo shows the working logic for validation of groups within groups.



来源:https://stackoverflow.com/questions/20616972/how-can-i-validate-a-group-within-another-group-and-maintain-separate-error-mess

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!