Over the past few weeks I’ve been working to migrate away from the Ajax Control Toolkit & various other ASP.NET built-in controls. My goal has been to get every page of our intranet portal down around 100K, with a maximum load time of < 1 second. I’ve made a lot of progress, but after cleaning up all the basic stuff (excess view state, duplicate references, compressed JS/CSS, sprites, etc…), I had to start looking for additional items…
Using Fiddler and FireBug, I started looking for resources that were increasing my download sizes and found that the ASP.NET validation controls were generating ~10K each time they were used in a module. Since my portal consists of injecting multiple user controls into a page, this number would vary page-by-page based on the number of modules that used the library on one page. Since I was using jQuery for all my scripting, I decided to implement jQuery Validation Plugin as a replacement for the built-in ASP.NET validation controls.
The idea was simple enough, but since I’m living in ASP.NET Web Form world (aka: One form per/page) this was a bit more difficult to implement.
Issue #1 – jQuery Validation by FIELDSET
As noted, the default setup of the validation plug in is to validate a FORM which isn’t possible with ASP.NET Web Forms. To get around this, I decided I was going to wrap all my forms in a FIELDSET with the class “validationGroup”. Using this class as my selection, I’m able to have multiple groups of controls wrapped in a FIELDSET validated separately.
To get started, you need to create a custom validation function that will recursively move up the elements/groups to find a FIELDSET with the class “validationGroup”, and then check all the input elements against the rules assigned.
Here is my custom validation function:
function ValidateAndSubmit(evt) {
var isValid = true;
// Get Validator & Settings
var validator = $("#aspnetForm").validate();
var settings = validator.settings;
// Find the parent control that contains the elements to be validated
var $group = $(evt.currentTarget).parents('.validationGroup');
// Grab all the input elements (minus items listed below)
$group
.find(":input")
.not(":submit, :reset, :image, [disabled]")
.not(settings.ignore)
.each(function (i, item) {
// Don't validate items without rules
if (!validator.objectLength($(item).rules()))
return true;
if (!$(item).valid())
isValid = false;
});
// If any control is the group fails, prevent default actions (aka: Submit)
if (!isValid)
evt.preventDefault();
}
Next, I need to trigger the validation for the current FIELDSET I’m working in based on on some action… like the click of a submit button. Since the default setting is to validation on submit, you need to disable this and register your ValidateAndSubmit function call when your event is triggered.
// Disable default/auto binding of all buttons
$("#aspnetForm").validate({
onsubmit: false,
ignore: ':hidden',
focusInvalid: true
});
// Bind the ASP.NET button with the ID "Search" to the "ValidateAndSubmit" custom validation function.
$('#<%= Search.ClientID %>').click(ValidateAndSubmit);
That’s it, with those three little little steps (Custom Validate Method, Disable Default/Auto Bind, Manual bind button to custom event), you now have a working validate by FIELDSET (or any other grouping control) solution.
Issue #2 – How to validate a group of ASP.NET Check Boxes
By default, ASP.NET will render a CheckBox or a CheckBoxList with an auto generated unique name attribute. This becomes a problem when you want to validate the group, since you can’t set a common name attribute for all the elements.
Here is an example of the HTML that would be rendered by a CheckBoxList with a layout of “Flow”.
<span id="CheckBoxGroup">
<input id="cbk1" name="cbk1" type="checkbox">Check Box 1</input>
<input id="cbk2" name="cbk2" type="checkbox">Check Box 2</input>
<input id="cbk3" name="cbk3" type="checkbox">Check Box 3</input>
</span>
<span class="jQueryValError"></span>
My solution to the problem required a custom validator and a custom errorPlacement function, for the jQuery validaiton plug-in.
First, I added a custom validator that looked at a group of check boxes that are inside a wrapping “Parent()” element. I then count the number of checked check boxes to make sure the limit required (e.g. Must check at least 3 check boxes) is greater than the minimum we set.
jQuery.validator.addMethod("minChecked",
function(value, element, param) {
var $p = $(element).parent();
var selected = $p.children('input[type=checkbox]:checked').length;
if (selected >= param) {
$p.children().removeClass('error');
$p.siblings('.error').remove();
return true;
}
$p.children('input[type=checkbox]').addClass('error');
In order to hookup this custom event to all the controls inside of a wrapping “Parent()” control, we use jQuery’s $().each function to call the validator’s rules() function.
$(".checkBoxGroup").children('input[type=checkbox]').each(function(){ $(this).rules("add", { minChecked: 3}); });
Second, our plug-in will by default put an error message next to the control(s) that triggered the error. I over ride the default behavior, we setup a “errorPlacement” function to put one error beside the wrapping “Parent()” control.
$("#<%= form1.ClientID %>").validate({
errorPlacement: function(error, element){
if(element.rules().minChecked > 0) {
var $p = $(element).parent();
if($p.siblings().hasClass("error") == false) {
error.insertAfter($p);
}
}
else {
error.insertAfter(element);
}
}
});
Here is what the form looks like when you have a error with your check boxes.
Here is source code used to create the example above.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Contact Form Demo</title>
<script src="styles/jQuery.js" type="text/javascript"></script>
<script src="styles/jQuery.Validate.js" type="text/javascript"></script>
<script src="styles/jQuery.Validate.AddOns.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery.validator.addMethod("minChecked",
function(value, element, param) {
var $p = $(element).parent();
var selected = $p.children('input[type=checkbox]:checked').length;
if (selected >= param) {
$p.children().removeClass('error');
$p.siblings('.error').remove();
return true;
}
$p.children('input[type=checkbox]').addClass('error');
return false;}, jQuery.validator.format("Please check at least {0} items."));
$(document).ready(function(){
$("#<%= form1.ClientID %>").validate({
rules: {
<%= FirstName.UniqueID %>: { required: true },
<%= LastName.UniqueID %>: { required: true },
<%= Email.UniqueID %>: { required: true, email: true },
<%= Phone.UniqueID %>: { required: true, phoneUS: true }
},
errorPlacement: function(error, element){
if(element.rules().minChecked > 0) {
var $p = $(element).parent();
if($p.siblings().hasClass("error") == false) {
error.insertAfter($p);
}
}
else {
error.insertAfter(element);
}
}
});
$(".checkBoxGroup").children('input[type=checkbox]').each(function(){ $(this).rules("add", { minChecked: 3}); });
$(".myGroupRandom").children('input[type=checkbox]').each(function(){ $(this).rules("add", { minChecked: 1}); });
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<fieldset>
<ol>
<li>
<label class="left">
First Name
</label>
<input type="text" id="FirstName" runat="server" /></li>
<li>
<label class="left">
Last Name
</label>
<input type="text" id="LastName" runat="server" /></li>
<li>
<label class="left">
Email
</label>
<input type="text" id="Email" runat="server" /></li>
<li>
<label class="left">
Phone
</label>
<input type="text" id="Phone" runat="server" /></li>
<li>
<label class="left">
Contact Method
</label>
<span class="checkBoxGroup">
<input type="checkbox" id="ReqEmail" runat="server" /><label>Email</label>
<input type="checkbox" id="ReqMail" runat="server" /><label>Mail</label>
<input type="checkbox" id="ReqPhone" runat="server" /><label>Phone</label>
<input type="checkbox" id="ReqNoContact" runat="server" /><label>No Contact</label>
</span></li>
<li>
<label class="left">
New Letter Type
</label>
<span class="myGroupRandom" >
<input type="checkbox" id="Checkbox1" runat="server" /><label>Company News</label>
<input type="checkbox" id="Checkbox2" runat="server" /><label>Press Releases</label>
<input type="checkbox" id="Checkbox3" runat="server" /><label>Deals</label>
<input type="checkbox" id="Checkbox4" runat="server" /><label>Employement</label>
</span></li>
<li>
<input type="submit" id="Submit" value="Submit" /></li>
</ol>
</fieldset>
</div>
</form>
</body>
</html>
#1 by Michael on July 17, 2013 - 7:11 pm
when I tried, the error shows multiple times beside the control as it was called according to the number of checked box. How can I avoid now to show multiple checkbox error messages? Thanks.
#2 by Zach on July 22, 2013 - 12:51 pm
Did you modify your error placement ?
#3 by David on March 1, 2012 - 10:57 am
Krishnam – I think the error is your “POST”, since you’re not actually sending any parameters to the WebService (since your Data is empty). Try changing POST to GET, and remove the Data line altogether and see if that fixes anything.
^_^ Months late.
#4 by krishnam on December 10, 2011 - 8:55 am
sorry i forgot to attach my code.
Untitled Page
$(document).ready(function(){
$(“#result”).click(function(){
$.ajax({
type: “POST”,
url: “AjaxPage.aspx/getDate”,
data: “{}”,
contentType: “application/json; charset=utf-8”,
dataType: “json”,
sucess: function(msg){
$(“#result”).html(msg.d);
}
});
});
});
Click here for time
———-
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Web.Services;
public partial class AjaxPage : System.Web.UI.Page
{
[WebMethod]
public static string getDate()
{
return “hello”;
}
}
can u plz help me??
#5 by krishnam on December 10, 2011 - 8:53 am
Hi,
when am trying to use jquery ajax. am getting the value from the called function but it is not showing on success of the $.ajax method..
#6 by Manoj C.S. on July 29, 2011 - 8:07 am
jquery validation not working on button-click
Hi all,
We are developing a asp.net application which collects the user information. We are using the jQuery validation as shown below
$(document).ready(function(){
$(“#formx”).validate();
$(‘input#phasedControl_txtDOB’).rules(‘add’,{
required:true,
DateFormat:true,
ValidDate:true,
Age:true
});
});
Date of Birth:
The reason we are not using the inbuilt validation which works on the input name and instead adding rules to each control is because we have aqualogic portal which inserts its own tags for the name and if we try to access them using it would return us the name which contains “:” in the name, like “phasedControl:txtDOB” and jQuery would throw syntax error coz the rules section would look like below
$(document).ready(function(){
$(“#formx”).validate({
rules: {
phasedControl:txtDOB: “required”
}
});
So we are adding the rules for each and every input control explicitly as shown below
$(‘input#phasedControl_txtDOB’).rules(‘add’,{
required:true,
DateFormat:true,
ValidDate:true,
Age:true
});
When i go to each textbox and enter the value and clear out the value and move to next text box the required field validator shows the message that “This field is required”. The issue is that when i submit the application by clicking the button, the validations doesn’t work and the next page will be shown. How to resolve this issue and stop the page from submitting if any validation errors are present?
I also tried using below piece of code but with no much help.
$(“input#phasedControl_btnNext”).click(function(evt) {
// Validate the form and retain the result.
var isValid = $(“#form_824”).valid();
// If the form didn’t validate, prevent the
// form submission.
if (!isValid){
evt.preventDefault();
}
});
I would be really thankful if anyone helps me out in resolving the above issue i.e. prevent the page from being submitted if there are any validation errors on that page.
Thanks in advance.
Manoj C.S.
#7 by Zach on August 2, 2011 - 10:50 am
Without trying to run the code, it sounds like something isn’t configured right. I understand your controls have weird names/id, but don’t forget you can also assign validation using css class names (just another option). The only time I’ve seen a button not trigger the validation event is when the button has been assigned the class name of “cancel” or the button was placed outside the form. Trapping the validation on button click is NOT the way it should be done, since this is already built into the validation plugin and the only reason it’s not firing is due to a coding error somewhere in your code. Start by building a simple prototype of your page in HTML that works, then add in a bit of your code at a time to track down your error. Additionally, you might want to look at Firebug to help you track down JS errors (which could be related to the validation issue).
#8 by Tomas on July 27, 2011 - 10:38 pm
ASP.NET build-in Validation controls offers client-side and server-side validation. If you have replaced them with jQuery validation when you have exposed your web application for hackers.
I do not find easy way to implement server-side and client-side jQuery validation. I have pushed to duplicate code and managed both jQuery validation and ASP.NET Validation controls which do server side validation.
Could you share your idea about server-side validation in your case?
#9 by Zach on July 28, 2011 - 9:13 am
Tomas,
Right, jQuery will only do client side (real-time) validation. Once the data hit’s the server, you have to determine the level of validation you need based upon your specific use case (e.g. Survey Form, Order Form, Comments, etc…). In general, I always use objects to manage my data (so I can write tests), which are strongly typed and perform the basic type checking validation (e.g. You can’t assign a string to an int.). If there is any special validation needed, I either write a custom validation function or use Fluent Validation for .NET. Over the past few months, I’ve relied more on Fluent Validation since it’s very easy to setup/configure/maintain. There are a few other validation librarys for .NET, but Fluent is a very easy to start with.
I also strongly suggest you install all your “3rd Party Packages” using NUGET. This is build into VS, will do all the basic setup and DLL inclusion in your project with the click of one button, and keep you up-to-date on updates to the DLL (e.g. Will tell you when v.4 is out.). You can find “FluentValidaiton” v.3.0.0.1 in NUGET right now.
#10 by Ajey Ghaligi on July 25, 2011 - 12:01 am
variable is obtained as txtAccount1.UniqueID
#11 by Ajey Ghaligi on July 25, 2011 - 12:00 am
Sorry I suppose variables were not copied in my earlier comment. Each of the rule is being performed on the fields as “”
Thanks.
#12 by Ajey Ghaligi on July 24, 2011 - 11:58 pm
Hey Zach,
I have 2 user controls which are being loaded dynamically in a page. I am using the validation jquery plugin to validate the fields in the user controls. Problem is when both the user controls are loaded in the page validation is being performed only in the first user control. Couls you please let me know how to call the validation functions of jquery for both the user controls in the page.
Following is my validation function in one of the user control:
$(document).ready(function () {
$(“#aspnetForm”).validate({
rules: {
: {
required: true,
minlength: 4
},
: {
required: true,
email: true,
showValue: true
},
: {
required: true,
maxlength: 25
}
},
messages:{
: “Account can not be blank.”,
: {
required: ” Client Name can not be blank”,
: “Please limit Client Name of 25 characters.”
}
}
});
#13 by Zach on July 25, 2011 - 9:15 am
So you have a page with 2 user controls and validation is only running on the first, right? If you using my code to validate various groups of control then make sure you apply “validationGroup” to the wrapping element (e.g.
fieldset class="validationGroup"
). This is used by the custom validation function to tell it which group of elements you validate. Let me know if this works for you, if not I can throw together a simple example and post online for you.Pingback: Weekly Links– 2010_12 (50 for Web Devs & Other Geeks) :MS-Joe (Joe Stagner)
#14 by Susan on November 22, 2010 - 1:41 pm
hi Zach, I am having a problem. I have a web form and multiple user controls in it. I am trying to implement jquery validation plugin. how do I define rules across multiple user controls and add them to the validator? Please help. Thanks.
#15 by Zach on November 22, 2010 - 3:30 pm
Susan,
In my post, issue #1 is what your dealing with. By default, jQuery validation will validate the entire form which means all User Control’s will be considered part of one form and all try to validate by default. Start by implementing the code I have posted under issue #1. The key here is that you need to nest all of your user control forms elements inside of some wrapper that can be used to group them together. In the example I use a FIELDSET with the class “validationGroup” to group all of my form controls by user controls.
If your having a specific error, let me know and maybe I can provide more insight.
Zach
#16 by Juan on November 10, 2010 - 3:25 pm
Zach you are great!!
Thank you very much, I made the changes and it works like a charm.
Juan
#17 by juan on November 9, 2010 - 8:14 pm
Sorry I made a mistake in my previous response, the Line that reads “The Coldfusion app has a script that will validate the same fields but it doens’t one by one” should be: “The ColdFusion app has a script that will validate the same fields but it Does it one by one”.
Thank you.
#18 by Zach on November 10, 2010 - 1:25 pm
Juan,
I understand what your saying now, very different from the original description. Basically, you want to show one message at a time and put focus on the error element. Here is a quick setup to do this, I’ve gone for short and sweet, this is based on my last example… Pay attention to the invalidHandler which is creating the message and setting the focus, and the errorPlacement which is blank causing no error message beside the field that caused the error.
#19 by juan on November 9, 2010 - 8:10 pm
Thank you for your response Zach. I didn’t send you the whole page because it is a long one. I have a button with type= submit that will activate the validate function and yes I didn’t enter any data in the required fields. I understand what you are telling me but what I am doing is converting a ColdFusion with many JavaScript to .Net with C#. The ColdFusion app has a script that will validate the same fields but it doesn’t one by one, so when I press submit in an empty form it will show me and alert telling about the first required field, will set the focus and then if I press submit again it will continue validating the rest of the fields stopping each time a required field is empty, that is what I mean by one by one, as you know the jquery validate function does the same but it display all the alerts at once (one after the other one). I am rewriting the scripts in Jquery because the original app uses three different scripts files that are complicated and don’t work with .Net because of how the way they used the DOM elements.
Hope I made my self clear, I don’t have the code with me that’s why I am not sending it.
Thank you.
#20 by Juan on November 9, 2010 - 4:23 pm
Great information Zach, thank you for that.
I do have a question, I have a form that validates few fields and display the error in an alert, How do I make stop after the first alert? righ now it shows the alerts for all the error fields. Then when entering the form the alert shows up after each keystroke. Here is the code and thank you in advance.
jQuery.validator.addMethod(
“selectNone”,
function(value, element) {
if (element.value == “none”)
{
return false;
}
else return true;
},
“Please select an option.”
);
$(document).ready(function() {
$(“#aspnetForm”).validate({
rules: {
: {
required: true },
: {
selectNone: true },
: {
selectNone: true },
: {
required: true },
: {
required: true },
: {
required: true },
: {
required: true },
: {
required: true },
: {
required: true },
: {
selectNone: true },
: {
required: true,
date: true
},
: {
required: true,
date: true
},
: {
required: true }
},
messages: {
: “Please enter a project name”,
: “Please select an Executive Sponsor”,
: “Please select a Managing Sponsor”,
: “Please select a Project Manager”,
: “Please enter a Project Background”,
: “Please enter Project Goals”,
: “Please enter Project Scope”,
: “Please enter a Financial Impact”,
: “Please select CSG review”,
: “Please select a Technology Focus”,
: “Please enter a valid Estimated Start Date”,
: “Please enter a valid Estimated Finish Date”,
: “Please enter Project Milestones”
},
errorPlacement: function(error, element) {
var msg = error[0].firstChild.data;
alert(msg);
}
});
});
#21 by Zach on November 9, 2010 - 5:38 pm
I’m going to assume there is more code than this on your page, but the only reason you should see all these alerts would be due to calling “Validate” on an incomplete form. The default setup of jQuery Validation only shows errors for the current element when you take focus away (aka: onBlur). The code you posted was obviously stripped of some data, but in general I don’t see anything wrong… Here is the rendered example of a similar setup, which only fires on each element…
#22 by sabarish on November 1, 2010 - 2:59 pm
main reason for using this function is that, i have a redio button, it has only 2 options(yes or no). but t required field comes near ‘YES’. i used tat element.parent. but still it is not showing. only for this i am going for tat errorPlacement function. is there any specific thing to do for radio button ??
#23 by Zach on November 1, 2010 - 6:30 pm
Your using ASP.NET right? Are you using a Flow or Table layout, I normally only use layout=”Flow”, this could be your problem.
#24 by sabarish on November 1, 2010 - 1:39 pm
same thing i use. but it overlaps with the adjacent textbox. if i don’t use this errorPlacement then t default error message is still overlapping. but the adjacent textbox hides t error message. so it is not looking bad. any idea how to handle this?? is there anything like error.insertdefault() or something??
#25 by Zach on November 1, 2010 - 2:22 pm
There is formatting options, I’m using insertAfter() but you could also use insertBefore() and wrap() as well.
.wrap() – Will wrap the validated element, you could use this to wrap the message in a div/span with a custom css class that formats/flows error message.
.insertBefore() – Would put the error before the validated element, this is normally used to put a astrik before the input box.
#26 by sabarish on November 1, 2010 - 12:37 pm
Hi, thanks for the solution. it really helped me. the 3rd option you gave really worked. thanks. now i have another problem. i have many controls in the fieldset. the error messages are coming correctly. i am having one radio button list. as you have given in the above example i used tat errorplacement. but now since t controls are close to each other, the error msg is overlapping. so inside tat errorpalcement method i want it to do inserafter only for radio button and for other controls it should do the default positioning. any idea???
#27 by Zach on November 1, 2010 - 1:21 pm
You can set this up in the errorPlacement, when you create your validate object. Below is the default one I use for all of my forms, it only applies special formatting to inputs with a type of “radio” or “checkbox”. You can tweak this to display/group/wrap anyway you want.
$(document).ready(function() {
$("#aspnetForm").validate({
onsubmit: false,
ignore: ':hidden',
focusInvalid: true,
errorClass: 'jQueryValError',
errorElement: 'span',
errorPlacement: function(error, element) {
if (element.is('input[type=radio]') || element.is('input[type=checkbox]')) {
var $p = $(element).parent();
if ($p.siblings().hasClass(this.errorClass) == false) {
if (error.text() != '')
error.insertAfter($p);
}
}
else {
if(error.text() != '')
error.insertAfter(element);
}
}
});
});
#28 by sabarish on October 31, 2010 - 4:08 pm
Hi. i also have the same problem.
see, i have 3 fieldsets which will get displayed based on the user selection of the dropdownlist. If they select ‘A’ then fieldset one and three will be displayed. if they select ‘B’ then fieldset one and two will be displayed. the fieldsets getting displayed will only be validated. the validation is working fine. but the problem is when i change the drop downlist value, the validator still shows error message in fieldset one as it is common for both. but i want it to reset the error message on dropdown change event. i tried calling the validator. but it is not getting called. how to reset or stop the msg to being displayed??
your help will be appreciated.
#29 by Zach on October 31, 2010 - 9:22 pm
Let me get this right, you have started filling out the form and you generated an error… then you want to choose a different set of forms (e.g. 1 & 3 -> 1 & 2) and you want to clear the error in form 1… hope this is righ, here are 3 options you have!
1. You can remove the rule and validate.
$("#").rules("remove");
$("#
").validate().element( "#" );
2. Manually clear error
$("label.error").hide();
$(".error").removeClass("error");
** This is based on using the CSS error class name “error”, I typically change mine but this should work if your using the default error class. You could hook this onto the dropdownlist click event.
$("#").click(function() {
$("label.error").hide();
$(".error").removeClass("error");
});
3. Finally, there is the resetForm() method, this does a full reset of the form the it’s default (before changes and display of error).
var validator = $("#").validate();
validator.resetForm();