【问题标题】:jQuery Validate Error Messages for Conditional Required and for GroupsjQuery 验证条件必需和组的错误消息
【发布时间】:2014-12-03 16:05:38
【问题描述】:

在使用 jQuery Validate 插件时,我一直在努力尝试让自定义错误消息在 3 种不同的情况下正确显示。

  • 我有一个组,并且只需要一个组成员。
  • 复选框字段的自定义消息。
  • 有条件地需要字段时显示错误消息。

我已经注意到这篇文章:How to show different error messages based on various conditions。这可能是我的问题解决方案的一部分吗?我还查看了Custom error messages for Groups within the jQuery Validation plugin,但它似乎没有解决只需要 1 个小组成员的问题,也没有解决我的问题。

我是 jQuery 和 fiddles 的新手,并且有一个无法正常工作的小提琴。我怀疑这是因为我没有指向 CSS 中使用的图形的链接,这些图形来自验证插件包中的 Milk 和 Marketo 示例。小提琴位于http://jsfiddle.net/cloudmech/myvmb95d/23/

这是我正在使用的代码。

jQuery:

$(document).ready(function() {
    $('#00NU00000049YHZ').change(function(){
       var checked = $(this).is(':checked');
       $('#company_information').toggle(checked);
       $('#company').prop('disabled', !checked)
   }).change();

    var $CompHdwDon = $('#00NU00000049YHj'),
    $SchedPickup = $('#00NU00000049YHt');

    $('#w2lForm').validate({
        debug: true,
        rules:{
            company: {
                depends: function(element) {
                    var checked = $('#00NU00000049YHZ').is(':checked');
                    return (checked);
                minlength: 3
                    }
                },             
            phone: {
                require_from_group: [1, '.phone_group'],
                phoneUS: true,
            },
            Mobile: {
                require_from_group: [1, '.phone_group'],
                phoneUS: true,
            },
            CompHdwDon: {
                required: checked=true
            },              
            SchedPickup: {
                required: checked=true
            },      
        },
        messages: {
            company: {
                depends: function(element) {
                    var checked = $('#00NU00000049YHZ').is(':checked');
                    return (checked);
                required: "Please provide the name of your company"
                }
            },
            phone_group: {
                required: "Either your regular or mobile phone is required"
            },
            phone: {
                required: "Either your regular or mobile phone is required"
            },
            Mobile: {
                required: "Either your regular or mobile phone is required"
            },
            CompHdwDon: {
                required: "This box must be checked for us to pick up a donation"
            },      
            SchedPickup: {
                required: "This box must be checked to schedule a donation pickup"
            },      
        },  
        // the errorPlacement has to take the table layout into account
        errorPlacement: function(error, element) {
            var n = element.attr("name");
            if (n == "phone" || n == "Mobile")
                error.appendTo(element.parent().next());
            else if (element.is(":radio"))
                error.appendTo(element.parent().next().next());
            else if (element.is(':checkbox'))
                error.appendTo(element.parent().next());
            else 
                error.appendTo(element.parent().next());
        },
        // set this class to error-labels to indicate valid fields
        success: function(label) {
            // set   as text for IE
            label.html(" ").addClass("checked");
        },
        highlight: function(element, errorClass) {
            $(element).parent().next().find("." + errorClass).removeClass("checked");
        }
        // specifying a submitHandler prevents the default submit, good for the demo
    });

});

HTML:

<BODY>
<div id="page-content-inner" class="resize">
<form id="w2lForm" action="https://www.xxxxx.com/servlet/servlet.WebToLead?encoding=UTF-8" method="POST">
<input type=hidden name="retURL" value="http://www.google.com"> 
</br>
<TABLE >
<TR>
    <TD class="label">This is for a Company:</TD>
    <TD class="field"><input  id="00NU00000049YHZ" name="00NU00000049YHZ" type="checkbox" value="0"  /></TD>
    <TD class="status"></TD>
<!--  If is This is for a Company == false, hide line below. If = true, show line below  -->
    <TD class="label" colspan="2">
    <div id="company_information">
    <label id="cmpnylbl" for="company" class="label" >Company:
    <input  id="company" maxlength="40" name="company" size="20" type="text"  class="required" /></div></TD>
    <TD class="status"></TD>
</TR>
<!--- create phone group below and require 1 of the two --->
<TR>
    <TD class="label"><label for="phone">Phone:</label></TD>
    <TD class="field"><input id="phone" class="phone_group" maxlength="40" name="phone" size="20" type="text" /></TD>
    <TD class="status"></TD>
    <TD class="label"><label for="mobile">Mobile:</label></TD>
    <TD class="field"><input id="mobile" class="phone_group" maxlength="40" name="mobile" size="20" type="text" /></TD>
    <TD class="status"></TD>
</TR>
<TR>
    <TD class="label">Computer Hardware Donation:</TD>
    <TD class="field"><input id="00NU00000049YHj" name="00NU00000049YHj" type="checkbox" value="1" class="required" /></TD>
    <TD class="status"></TD>
    <TD class="label">Schedule Pickup:</TD>
    <TD class="field"><input id="00NU00000049YHt" name="00NU00000049YHt" type="checkbox" value="1" class="required" /></TD>
    <TD class="status"></TD>
</TR>
<TR><TD class="field" COLSPAN="4"><input type="submit" name="submit"></TD></TR>
</TABLE>
</form>
</div>
</BODY>

CSS:

body, input, select, textarea { font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; }
img {
    border: 0px;
}

#resize{
    width: 500px;
}

.clear {
    clear: both;
}

input { border: 1px solid black; margin-bottom: .5em;  }

input.error { border: 2px solid red; }

label.error {
    display: block;
    color: red;
    font-style: italic;
    font-weight: normal;
    background: url('images/unchecked.gif') no-repeat;
    padding-left: 16px;
    margin-left: .3em;
}
label.valid {
    background: url('images/checked.gif') no-repeat;
    display: block;
    width: 16px;
    height: 16px;
}

form table td {
    padding: 5px;
}

form table input {
    width: 200px;
    padding: 3px;
    margin: 0px;
}

textarea {
    width: 400px
}

td.label {
    width: 150px;
}

tr.required td.label {
    font-weight: bold;
    background: url( 'images/backRequiredGray.gif') no-repeat right
        center;
}


td.field input.error, td.field select.error, tr.errorRow td.field input,tr.errorRow td.field select {
    border: 2px solid red;
    background-color: #FFFFD5;
    margin: 0px;
    color: red;
}

tr td.field div.formError {
    display: none;
    color: #FF0000;
}

tr.errorRow td.field div.formError {
    display: block;
    font-weight: normal;
}

#w2lForm .table {
  border-spacing: 0px;
  border-collapse: collapse;
  empty-cells: show;
}

#w2lForm .label {
  padding-top: 2px;
  padding-right: 8px;
  vertical-align: top;
  text-align: right;
  width: 125px;
  white-space: nowrap;
}

#w2lForm .field {
  padding-bottom: 10px;
  white-space: nowrap;
}

#w2lForm .status {
  padding-top: 2px;
  padding-left: 8px;
  vertical-align: top;
  width: 246px;
  white-space: nowrap;
}

#w2lForm .textfield {
  width: 150px;
}

#w2lForm label.error {
  background:url("images/unchecked.gif") no-repeat 0px 0px;
  padding-left: 16px;
  padding-bottom: 2px;
  font-weight: bold;
  color: #EA5200;
}

#w2lForm label.checked {
  background:url("images/checked.gif") no-repeat 0px 0px;
}

作为最后一个问题,当我让这一切正常工作时,我想使用所示的 servlet 发布它。我是否需要将以下内容添加到我的 jQuery 中,是否需要构建 Ajax 处理程序或什么都不做?我观察到,当 servlet 的完整 URL 可用时,它似乎“按原样”提交。

submitHandler: function(form) {
   form.submit();
}

修改后的 jQuery:

$(document).ready(function() {

    $('#00NU00000049YHZ').change(function(){
       var checked = $(this).is(':checked');
       $('#company_information').toggle(checked);
       $('#company').prop('disabled', !checked)
   }).change();

    $('#00NU00000049YHZ').on('change', function () {  // fire on change
        $('[name="company"]').valid();  // evaluate rules on company
    });


    $('#w2lForm').validate({
        debug: true,

        rules:{
            company: {
                required: {
                    depends: function(element) {
                        return $('#00NU00000049YHZ').is(':checked');
                    }
                },
                minlength: 3
            },             
            phone: {
                require_from_group: [1, '.phone_group'],
                phoneUS: true,
            },
            Mobile: {
                require_from_group: [1, '.phone_group'],
                phoneUS: true,
            },
            "00NU00000049YHj": {
                required: true
            },              
            "00NU00000049YHt": {
                required: true
            },      
        },
        messages: {
            company: {
                required: "Please provide the name of your company",
                minlength:  "Please type at least {0} characters"
            },
            phone: {
                require_from_group: "Either your regular or mobile phone is required"
            },
            Mobile: {
                require_from_group: "Either your regular or mobile phone is required"
            },
            "00NU00000049YHj": {
                required: "This box must be checked for us to pick up a donation"
            },      
            "00NU00000049YHt": {
                required: "This box must be checked to schedule a donation pickup"
            },      
        },  
        // the errorPlacement has to take the table layout into account
        errorPlacement: function(error, element) {
            var n = element.attr("name");
            if (n == "phone" || n == "Mobile")
                error.appendTo(element.parent().next());
            else if (element.is(":radio"))
                error.appendTo(element.parent().next().next());
            else if (element.is(':checkbox'))
                error.appendTo(element.parent().next());
            else 
                error.appendTo(element.parent().next());
        },
        // set this class to error-labels to indicate valid fields
        success: function(label) {
            // set &nbsp; as text for IE
            label.html("&nbsp;").addClass("checked");
        },
        highlight: function(element, errorClass) {
            $(element).parent().next().find("." + errorClass).removeClass("checked");
        }

    });

});

【问题讨论】:

    标签: jquery jquery-validate


    【解决方案1】:

    你的最后一个问题先...

    submitHandler 回调函数仅在您想要更改插件的默认行为时才需要。默认行为是在所有数据输入通过验证之前将阻止表单提交,然后将其提交到form元素的action属性中的URL。

    这段代码本质上是默认的,所以整个submitHandler是多余的,可以省略.validate()...

    submitHandler: function(form) {
       form.submit();  // <- already the default behavior
    }
    

    但是,如果您想通过ajax 提交表单,那么您可以按如下方式使用它...

    submitHandler: function(form) {
       // your ajax function here
       return false;
    }
    

    其次,你的代码在这里真的坏了......

    rules:{
        company: {
            depends: function(element) {
                var checked = $('#00NU00000049YHZ').is(':checked');
                return (checked);
            minlength: 3
                }
            },
    ....
    messages: {
        company: {
            depends: function(element) {
                var checked = $('#00NU00000049YHZ').is(':checked');
                return (checked);
            required: "Please provide the name of your company"
            }
        }, 
    

    depends 不是规则; depends 是一个规则的属性,它只是简单地打开和关闭规则,你不能有一个键:值对在函数内部浮动。这应该会导致各种错误。而且您将永远不会messages 中看到depends,因为该消息不依赖于任何东西......它只是附加到一个规则。

    据推测,您希望 company 字段 required 取决于另一个条件...

    rules:{
        company: {
            required: {
                depends: function(element) {
                    return $('#00NU00000049YHZ').is(':checked');
                }
            },
            minlength: 3
        },
        ....
    },
    messages: {
        company: {
            required: "Please provide the name of your company",
            minlength:  "Please type at least {0} characters"
        },
        ....
    },
    ....
    

    第三,这是什么??

    CompHdwDon: {
        required: checked=true
    },              
    SchedPickup: {
        required: checked=true
    },
    

    required 方法的值只能是布尔值或函数 (depends) 时,不能将 checked=true 作为值。

    CompHdwDon: {
        required: true
    },              
    SchedPickup: {
        required: true
    },
    

    最后,require_from_group 方法/规则将创建一个条件,即使您只希望组中的一个字段为required,错误消息也会出现在所有字段上。 The solution is to use the groups option, which will simply group all messages for this particular group of fields into one。然后可以使用errorPlacement 选项实现消息的准确放置。


    编辑

    例如,您的代码。

    rules: {
        Mobile: {
            require_from_group: [1, '.phone_group'],
            phoneUS: true
        },
    },
    messages: {
        Mobile: {
            required: "Either your regular or mobile phone is required"
        },
    }
    

    rules 下的方法与messages 下的方法不匹配...您可以省略一些,但不能添加任何不存在的方法。

    messages下对应的key:value对需要匹配...

    messages: {
        ....
        Mobile: {
            require_from_group: "Either your regular or mobile phone is required"
        },
        ....
    

    编辑 2:

    CompHdwDon: { // <- this should match the NAME of the field!
        required: true
    },  
    

    这段代码没有做任何事情,因为你没有name="CompHdwDon" 的字段。它只是似乎起作用,因为您在复选框上有class="required"。在这种情况下,插件使用required class 来设置规则。在.validate() 内声明规则或内联声明它们,但无需同时进行。

    改变这个...

    <TD class="label">Computer Hardware Donation:</TD>
    <TD class="field"><input id="00NU00000049YHj" name="00NU00000049YHj" type="checkbox" value="1" class="required" /></TD>
    

    进入这个...

    <TD class="label">Computer Hardware Donation:</TD>
    <TD class="field"><input id="CompHdwDon" name="CompHdwDon" type="checkbox" value="1" /></TD>
    

    编辑 3

    highlight: function(element, errorClass) {
        $(element).parent().next().find("." + errorClass).removeClass("checked");
    }
    

    您不需要在errorClass 对象上附加句点。它已经内置。此外,当使用highlight 时,您通常还需要unhighlight

    你也不应该需要.find(errorClass),因为这个类总是在切换,highlight 只有在字段无效时才会触发。另请记住,highlight 仅针对正在评估的特定字段。

    highlight: function(element, errorClass) {
        $(element).parent().next().removeClass("checked");
    },
    unhighlight: function(element, errorClass) {
        $(element).parent().next().addClass("checked");
    }
    

    编辑 4

    单击复选框时立即触发另一个字段上的错误消息意味着我们需要一个事件处理程序。然后我们只需触发.valid() 方法来评估现场规则。

    $('#00NU00000049YHZ').on('change', function () {  // fire on checkbox change
        $('[name="company"]').valid();  // evaluate rules on company
    });
    

    或者这个……

    // assuming your existing change handler is already working...
    $('#00NU00000049YHZ').change(function(){
        var checked = $(this).is(':checked');
        $('#company_information').toggle(checked);
        $('#company').prop('disabled', !checked);
        $('[name="company"]').valid();  // evaluate rules on company
    }).change();
    

    为了安全起见,请将此 change 处理程序放在您调用 .validate() 之后。

    【讨论】:

    • 很好的回复 Sparky。公司字段是必需的,具体取决于复选框is checkedCompHdwDon 是需要勾选的复选框。 SchedPickup 也一样。我无法为群组显示自定义消息,只有标准消息,如您所述,我可以控制其位置。
    • @crmprogdev,当您不使用required 规则时,您无法为required 设置自定义消息。当您使用required_from_group 规则时,您可以在require_from_group 上设置自定义消息。请参阅我编辑的答案。慢慢来,放慢脚步……
    • 几天来一直在努力解决这个问题。哈哈! .phone_group 是一个 CSS 类,而不是使用 add group 方法创建的组。文档在这方面令人困惑。 require_from_group终于解决了群的自定义消息问题!进步! :) 显示时,仍然会收到复选框的标准消息,而公司字段上的切换框没有消息。
    • @crmprogdev,好吧,CompHdwDon 应该代表什么?为了让插件使用它,它必须是元素的name,但我在您的 HTML 中没有看到具有此名称的元素。你认为它工作的原因是因为你在复选框上有class="required"Maybe study the wiki page along with the docs.
    • @crmprogdev,SO 问题应该针对某个问题,而不是用于解决一大堆不相关的语法和编程问题。无论如何,我已经指出了您的代码被破坏的大部分区域,并用最新的答案编辑了我的答案。如果您仍然有问题,请提出一个新问题,尝试将其集中在特定问题上。谢谢。
    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多