Click here to Skip to main content
Click here to Skip to main content

Working with multiple ValidationGroups simultaneously on the client-side

By , 10 Dec 2010
Rate this:
Please Sign up or sign in to vote.

Introduction

With ASP.NET 2.0, we got a new 'ValidationGroup' property on validators as well as controls. This property enables us to group together certain controls and their respective validators under one common group. On page submit, we can tell the runtime which ValidationGroup to consider and ignore the rest. By using a ValidationGroup, we can avoid having to manually enable/disable validations. But there's a small problem -- only one ValidationGroup can be specified during submit. This article shows a trick to work with multiple ValidationGroups on the client-side during page submit.

Background

To begin with, I have four ValidationGroups, out of which three are active at any given point of time, during page-submit. Whenever the validation fails on any control, the background color of the control becomes red.

The example consists of an ASPX page which calls a UserControl. This example can be easily extended to any number of ValidationGroups in any number of UserControls.

First, the User Control -- I have a DropDownList in the UserControl which sets up a criteria for conditional validation. By "conditional validation", I mean a particular ValidationGroup is ignored in the Page_ClientValidate() call based on what the user has selected in the DropDownList.

Broadly, there are two sets of ValidationGroups, namely ValidationGroup="ValSumm1" and ValidationGroup="ValSumm9". So if ValidationGroup="ValSumm1" is active, then ValidationGroup="ValSumm9" is ignored, and vice-versa. There is also a third ValidationGroup in the UserControl on the DropDownList: ValidationGroup="ValSummG" -- to make sure that the user selects a criteria.

Listing 1: UserControl markup
<asp:DropDownList ID="ddl1" runat="server" AppendDataBoundItems="true">
  <asp:ListItem Text="Select Validation Group" Value=""></asp:ListItem>
  <asp:ListItem Text="ValSumm1" Value="bb"></asp:ListItem>
  <asp:ListItem Text="ValSumm9" Value="cc"></asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" 
   runat="server" ControlToValidate="ddl1" 
   ErrorMessage="ValGroup is required." 
   Text="ValGroup is required" 
   VALIDATIONGROUP="VALSUMMG">
</asp:RequiredFieldValidator>
<asp:TextBox ID="txt1" runat="server" ></asp:TextBox>
<asp:RequiredFieldValidator ID="Req1" runat="server" 
   ControlToValidate="txt1"  ErrorMessage="Text1 is required." 
   Text="Text1 is required" 
   VALIDATIONGROUP="VALSUMM1"></asp:RequiredFieldValidator>
<asp:DropDownList ID="ddl2" runat="server" 
                AppendDataBoundItems="true" >
  <asp:ListItem Value="">Select Item</asp:ListItem>
  <asp:ListItem Value="1" Text="1"></asp:ListItem>
  <asp:ListItem Value="2" Text="2"></asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="Req4" runat="server" 
      ControlToValidate="ddl2"  ErrorMessage="Item is required." 
      Text="Item is required" VALIDATIONGROUP="VALSUMM1">
</asp:RequiredFieldValidator>
</fieldset>
<asp:TextBox ID="TextBox1" runat="server" 
  VALIDATIONGROUP="VALSUMM9" ></asp:TextBox>
<asp:RequiredFieldValidator ID="Req2" runat="server" 
  ControlToValidate="TextBox1" ErrorMessage="Text2 is required." 
  Text="Text2 is required." VALIDATIONGROUP="VALSUMM9">
</asp:RequiredFieldValidator>
<asp:TextBox ID="TextBox2" runat="server" 
          VALIDATIONGROUP="VALSUMM9"></asp:TextBox>
<asp:RequiredFieldValidator ID="Req3" runat="server" 
  ErrorMessage="Text3 is required." ForeColor="Red" 
  ControlToValidate="TextBox2" 
  Text="Text3 is required." VALIDATIONGROUP="VALSUMM9">
</asp:RequiredFieldValidator>

The parent ASPX page has a ValidationSummary for the complete app, a ValidationGroup: ValidationGroup="ValSummP". So the parent page and the UserControl together makes it four unique ValidationGroups.

Listing 1: ASPX markup
<asp:UpdatePanel ID="UpdatePanel2" 
        runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:ValidationSummary ID="SUMMARY1" runat="server" />
    <fieldset>
    <asp:TextBox ID="TextBox1" runat="server" ></asp:TextBox>
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
         ControlToValidate="TextBox1" runat="server" 
         Text="RequiredFieldValidator" 
         ErrorMessage="RequiredFieldValidator" 
         VALIDATIONGROUP="VALSUMMP" >
    </asp:RequiredFieldValidator>  
    <br />
<uc1:ValidationUserControl ID="ValUC"  runat="server"  /><br /><br />
<asp:Button ID="btn2" runat="server" 
          Text="Submit2" OnClientClick="return ValidateNow();" 
          onclick="btn2_Click" />
    </fieldset>
</ContentTemplate>
</asp:UpdatePanel>

Currently, I have hardcoded the ValidationGroups in the UserControl. So if you are using just a single instance of this control in a page, it won't be a problem. However, we can pass the ValidationGroup name from the parent calling page to the UserControl and hence make the UserControl's ValidationGroup name dynamic. The thing to focus here is how to validate a page, client-side as well as server-side, when we have more than one ValidationGroup running concurrently. Broadly speaking, this whole thing is done in three steps:

  • Step 1 -- On the parent page for a given ValidationGroup, call the function ValidatorValidate() passing the relevant ValidationGroup, which will update the IsValid property of all validators under that group. Next on the parent page again, call the function fnOnUpdateValidators() passing the relevant ValidationGroup, which will set the background color of any control on which validation fails.
  • Step 2 -- The above two functions are called in the UserControl, for all the active ValidationGroups participating in the current request.
  • Step 3 -- Finally, in the parent page, set the page level validation status and update the ValidationSummary control by the following two calls:
  • ValidatorUpdateIsValid();
    ValidationSummaryOnSubmit(); 

Now check if the complete page is valid on the client:

if (!Page_IsValid) {
  return false;
}

A few things to notice here ---

<script language="javascript" type="text/javascript">
function ValidateNow() {
    //Check this page's validators
    My_PageClient_Validate("ValSummP");
    fnOnUpdateValidators("ValSummP");
    //Check UserControl's validators
    abc();
    //Finally run comple app level validator validate & submit
    ValidatorUpdateIsValid();
    ValidationSummaryOnSubmit();
    if (!Page_IsValid) {
        return false;
    }
    return true;
}
function My_PageClient_Validate(CurrValGrp) {
    for (i = 0; i < Page_Validators.length; i++) {
        var val = Page_Validators[i];
        if (val.validationGroup == CurrValGrp) {
            ValidatorValidate(Page_Validators[i], CurrValGrp, null);
        }
    }
}
function fnOnUpdateValidators(CurrValGrp) {
    for (var i = 0; i < Page_Validators.length; i++) {
        var val = Page_Validators[i];
        var ctrl = document.getElementById(val.controltovalidate);
        if (ctrl != null && ctrl.style != null) {
            if (val.validationGroup == CurrValGrp) {
                if (!CheckValidatorsForControl(ctrl)) {
                    ctrl.style.backgroundColor = 'red';
                }
                else {
                    ctrl.style.backgroundColor = '';
                }
            }
        }
    }
}
</script>

The main client-side function which sets the validator's IsValid property is ValidatorValidate(Page_Validators[i], CurrValGrp, null);.

I run the ValidatorValidate function for all the relevant ValidationGroups which I want.

The My_PageClient_Validate() function takes the active ValidationGroup name and basically sets up the IsValid property of all the validator controls which has this supplied ValidationGroup. This is a little different from the standard PageClient_Validate version, in the sense that I make sure the validators fall under the ValidationGroup I 'm trying to validate so that they do not nullify my earlier validation results. Hence, the ValidatorValidate call is inside the if check.

Next is the function fnOnUpdateValidators(), which basically sets the background color of the control on which the validation failed. The above two steps are repeated in the UserControl too.

So summarily -- I update the validator control's IsValid property, and based on that, set the background color of the control on which validation failed - first for the parent page, and then the UserControl. Once all the relevant ValidationGroups are validated, I set up the page level Page.IsValid boolean value by calling these two functions:

ValidatorUpdateIsValid();
ValidationSummaryOnSubmit();

Notice the ValidationSummaryOnSubmit() function, I didn't supply any ValidationGroup. So it covers all ValidationGroups that are currently relevant. On the server side, it's just a Page.IsValid check.

That's it. The complete source code is attached.

Hope this article helps someone. Thanks for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

GG123

United States United States
http://simpledotnetsolutions.wordpress.com/

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 10 Dec 2010
Article Copyright 2010 by GG123
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid