Click here to Skip to main content
Email Password   helpLost your password?

Sample Image - MultiDependValidator.jpg

Introduction

ASP.NET validators are a great time saver. However, they lack the built in ability to validate multiple controls on the client side. Luckily, this is easily fixed.

Background

It is fairly easy to use something like:

<asp:RequiredFieldValidator id=PhoneRequired runat="server" 
Display="Dynamic" ErrorMessage="*" ControlToValidate="Phone" />

This requires that the user fills in the Phone field. What if you have a Phone field and an Email field. You could require both fields, but you might want to allow the user to enter only one of these fields. In this case, you couldn't use RequiredFieldValidator.

Example

Requires that user enters Phone or Email. Client side validation updates when either field is changed.

Solution

Update!

I have added a user control / class based on Multi-Validator which is extended from CustomValidator, this makes creating validators that are dependent on multiple controls even easier. However, it is currently written to work with ASP.NET 2.0 beta 1 or later. See attached zip file for the source and two examples which use the classes. The following example works with ASP.NET 1.0.

Fields and CustomValidator

<b>Phone: </b><asp:TextBox id="Phone" runat="server"><br />
<b>Email: </b><asp:TextBox id="Email" runat="server">
<asp:Button id="Submit" Text="Submit" /><br />

<%-- AtLeastOneContact Custom Validator --%>
<asp:CustomValidator id="AtLeastOneContact" runat="server"  
  ErrorMessage="Phone or Email Required" 
  Display="Dynamic"
  OnServerValidate="AtLeastOneContact_ServerValidate" 
  ClientValidationFunction="AtLeastOneContact_ClientValidate" />

Note: Do not set ControlToValidate. Doing so causes validation to fail when that field is empty. In ASP.NET 2.0, I recommend setting ValidateEmptyText="true".

Server Side Part

' Server Side Validation

Sub AtLeastOneContact_ServerValidate(ByVal source As Object, _
  ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) 
    'Requires that either Phone or Email is not empty

    If Phone.Text & Email.Text <> "" Then
        args.IsValid = true 
    Else
        args.IsValid = false 
    End If 
End Sub

Client Side Part

<%-- Client Side Validation --%>
<script type="text/vbscript" language="vbscript">
<!--
    Sub AtLeastOneContact_ClientValidate(source, args)
        'Requires that either Phone or Email is not empty

        If document.getElementById("<%= Phone.ClientID %>").value & _
           document.getElementById("<%= Email.ClientID %>").value <> "" Then
            args.IsValid = true
        Else
            args.IsValid = false
        End If
    End Sub
'-->
</script>

Creating the dependency

<%-- This configures the validator to automatically--%> 
<%-- update when either of these controls is changed --%>
<script type="text/javascript">
<!--
  ValidatorHookupControlID("<%= Phone.ClientID %>", 
     document.all["<%= AtLeastOneContact.ClientID %>"]);
  ValidatorHookupControlID("<%= Email.ClientID %>", 
     document.all["<%= AtLeastOneContact.ClientID %>"]);
//-->
</script>

This is where the magic happens... This informs the built invalidation subroutines to update validation whenever one of these controls change. You can easily add as many controls as needed to a single validator's dependencies. The ValidatorHookupControlID function is part of the standard Microsoft validation scripts.

Note this code must appear after the automatically added ValidatorOnSubmit() function. This function is added to the page when you use validation controls. The best place for this script is just before the </form> tag.

I normally use Page.RegisterStartupScript to add this script to the page, however that method is harder to read and understand. I do this in the PreRender event for the CustomValidator.

Other Examples

You can use this method to create complex validations. For example, I have a drop down list with various options. One of the options is "other / see comments". The drop down list also includes a blank entry "select option". I created a validator that requires that the user enters a value for the dropdown, and if they select "other / see comments" then it requires that something is in comments.

You can validate two drop down lists against each other. For example, if you were selling clothes you could have a dropdown for the type of item and one for color selection. Then in your validator, you could show the error message if that item is not available in that color. That is you sell shirts in blue, green and red. But only sell pants in blue and green.

Demo

The zip file contains a single working aspx page. Try it out. Note that validation error messages do not display until you have updated one of the controls or try to submit. You can add Page.Validate to the Page_OnLoad event if you want validation error messages to appear immediately.

History

Thanks

If you read this article then please leave a comment below.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
General'undefined is null' or not an object javascript error.
boydd_uk
7:07 9 Apr '09  
This is caused by the following code:

ValidatorHookupControlID("<%= txtWork.ClientID %>",
document.all["<%= AtLeastOneContact.ClientID %>"]);
ValidatorHookupControlID("<%= txtMobile.ClientID %>",
document.all["<%= AtLeastOneContact.ClientID %>"]);
ValidatorHookupControlID("<%= txtHome.ClientID %>",
document.all["<%= AtLeastOneContact.ClientID %>"]);

When I removed these lines of codes then there is no javascript error.

Can someone tell me why this is happening as it's driving me nuts.
GeneralRe: 'undefined is null' or not an object javascript error.
boydd_uk
7:12 9 Apr '09  
just re-read the document carefully!!

This code needs to be placed after the validator in the aspx file. As the author says at the end of the /form

Opps
GeneralSeems nice but can't make it work!
ricaforrica
19:31 15 Jul '08  
Hello!

Great article, but I didn't manage to make it workFrown

I'd like to have an AtLeastOneValidator and my code is the following:

ASCX
<asp:textbox id="txtHour" runat="server" width="30px" xmlns:asp="#unknown">< /asp:TextBox><asp:label id="letterH" runat="server" text="h">< /asp:label>
<asp:textbox id="txtMinute" runat="server" width="30px">< /asp:TextBox><asp:label id="letterM" runat="server" text="m">< /asp:label>
<aspextendedvalidation:atleastonevalidator id="AtLeastOne" öninit="AtLeastOne_Init" runat="server" display="Dynamic" errormessage="Por favor, indicar horas e/ou minutos" xmlns:aspextendedvalidation="#unknown">< /aspExtendedValidation:AtLeastOneValidator>


ASCX.VB
Protected Sub AtLeastOne_Init(ByVal sender As Object, ByVal e As System.EventArgs)
Dim alov As AtLeastOneValidator = CType(sender, AtLeastOneValidator)
alov.ValidationDependencies.Add(txtHour)
alov.ValidationDependencies.Add(txtMinute)
End Sub
Protected Sub btNew_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btNew.Click

Dim bRollback As Boolean = False
Try
Page.Validate()
If Page.IsValid Then
...
End Sub


It is not working neither in IE7 nor in Firefox3.

In IE7, I get an error when I click the btNew button (with both fields empty or at least one of them filled):
Error:object expected in line 458 - this occurs in function AtLeastOneValidator_ClientValidate(val, args);
In Firefox, when I click the btNew button nothing happens, (again with both fields empty or at least one of them filled).
In both browsers, I can enter in debug mode in the AtLeastOne_Init sub.

Can you please help me with this issue?
Thanks in advance!

Regards,

Ricardo.

Ps: please ignore if the post added this tag xmlns:asp="#unknown" in some of the ascx code lines Smile
Generaleh ... I think this validates for BOTH ....
macAsp
5:25 14 Jul '08  
to be filled ... as opposed to either !


' Server Side Validation
Sub AtLeastOneContact_ServerValidate(ByVal source As Object, _
ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs)
'
Requires that either Phone or Email is not empty
If Phone.Text & Email.Text <> "" Then
args.IsValid = true
Else
args.IsValid = false
End If
End Sub


Big Grin
GeneralRe: eh ... I think this validates for BOTH ....
DanielHac
10:37 14 Jul '08  
The example was to validate an either condition, which is not possible with standard validation controls.
GeneralRe: eh ... I think this validates for BOTH ....
macAsp
0:24 15 Jul '08  
What is the english for

If Phone.Text & Email.Text <> "" Then
?

This validates to true if BOTH are not empty. I think you are trying to validate if EITHER one is not empty .... no ?


D'Oh!

Sorry - "blonde moment"
GeneralThis doesn't work.
Christopher Hill
7:13 19 Mar '08  
I tried it... didn't work. Validator doesn't pop up.
Generalthanks
atenea33
10:02 4 Sep '07  
Smile
Generalcareful using document.all
Jon Kruger
4:46 18 Dec '06  
In your example code, you have...

document.all[id]

This doesn't work in Firefox (don't think it works in Opera or Safari either, for that matter).

Instead of document.all[], use document.getElementById(id).

Great tip, this is really helpful.

Jon
GeneralRe: careful using document.all
metweek
13:15 15 Oct '07  
Not to mention to use of vbscript on the client side.
GeneralReally a nice one
Venkat Eswaran
7:47 25 Oct '06  
Great work. It simplified my work... Smile

Venky

GeneralNice tip.
sachinsrb
2:21 20 Jul '06  
Hi,

I needed to validate multiple controls, and your article really helped in understanding the same.

Really nice Big Grin.

Regards,
Sachin:
Generaleasy fast
rperetz
12:37 8 Jun '06  
very good, just take out the ControlToValidate and works like a charm.
may be peace upon you my programer angel

Ronnie
NewsMultipleFieldsValidator for ASP.NET 2.0
Adam Tibi
11:28 20 Mar '06  
This is a link to a similar control made for ASP.NET 2.0

http://www.codeproject.com/aspnet/MultipleFieldsValidator.asp

Regards

Make it simple, as simple as possible, but not simpler.
QuestionVS2005?
Bill44060
6:52 23 Dec '05  
Hi,

This is great! I just can't seem to get it to build in VS2005 RTM. Do you have a sln file with your component and 2 aspx pages?

thanks in advance,
Bill
AnswerRe: VS2005?
Bill44060
8:17 23 Dec '05  
Daniel,

Ok - figured it out. Needed to add a couple namespaces:

Imports System.Web.UI.WebControls
Imports System.Text

Then all I needed to do was to add an App_Code folder to my web project and put the code in there.

Very Cool!

thanks,
Bill

GeneralHow about multiple rows?
cbwongsteve
1:31 5 May '05  
I am so lazy that i haven't tried your code but I am interested whether it works when the datagrid / datalist has multiple rows. In this situation, will the validation validate the specific row only ? How would I handle for multiple rows? Thank you.

Confused
GeneralRe: How about multiple rows?
Anonymous
1:44 5 May '05  
If you want all rows validated simultaniously then it's easy just add control as a dependency during the row data bound event. If you want rows to validate independently then in some cases you may need to use validation groups which is only avaiable in asp.net 2.0 (currently in beta) Bottom line it can be done but how to do it depends on the situation.
GeneralRe: How about multiple rows?
DanielHac
1:46 5 May '05  
Sorry, previous post was by me... forgot to sign in.
QuestionRe: How about multiple rows?
mmengel
17:30 13 Jun '07  
DanielHac:

Any chance you could provide a code sample of adding control dynamically in row data bound event? I'd like to use the control, after clicking the Edit button on a GridView, to validate two controls, found in EditItemTemplates, against each other.

Example: click on Edit button and a dropdownlist and a text box show up. DDL cannot equal X if text box is empty, and vice versa, if DDL = X, text box must contain a value.

Thanks,
Mike
AnswerRe: How about multiple rows?
kable33
12:12 25 Sep '08  
I'm using this on a gridview in .net 2.0. I took the code from IfOtherValidator_Init, modified it and placed it in the Gridview Databound event. Here is the VB.net code, I hope it helps someone:

Protected Sub gridSVL_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)
For Each rowSVL As GridViewRow In gridSVL.Rows
Dim ddlReasonAbsent As DropDownList = rowSVL.FindControl("ddlReasonAbsent")
Dim txtHoursAttend As TextBox = rowSVL.FindControl("txtHoursAttend")
Dim val As MultiValidator = CType(rowSVL.FindControl("IfOtherValidator"), MultiValidator)
Dim js As New StringBuilder

val.ValidationDependencies.Add(txtHoursAttend) '0
val.ValidationDependencies.Add(ddlReasonAbsent) '1

'Write Client Script
val.ClientValidationFunction = "IfOtherValidator_ClientValidate"

js.Append("function ").Append(val.ClientValidationFunction).Append("(val, args) {").AppendLine()
js.Append(" args.IsValid = (ValidatorDependencyValue(val, 0) == '0' || ValidatorDependencyValue(val, 1) == '0');").AppendLine()
js.Append("}").AppendLine()

Page.ClientScript.RegisterClientScriptBlock(Me.GetType, val.ClientValidationFunction, js.ToString, True) 'ASP.NET 2.0
Next
End Sub
GeneralUse CssClass
Dave Bacher
4:57 12 Apr '05  
One option to make the client side code easier to maintain (server side could be improved as well using this technique) would be to use a CssClass to identify the controls involved in the or relationship. This is readily available through DOM, and by grouping controls by CssClass, when you add a new contact method you only have to tag it with the right CssClass so the client knows.

A similar approach would be using a div or panel to encapsulate the controls, and locating the div/panel by ID -- for the case "enable/disable" or "show/hide" based on a drop down (for example), this might make a lot of sense.
GeneralRe: Use CssClass
DanielHac
13:25 12 Apr '05  
You might want to take a look at the class based implementation that I have started working on for asp.net 2.0.

It allows you to access dependencies using a dependencey index making writing the client side function fairly easy.

Also, although it's an intresting idea. I don't think I should use CssClass for something not presentation oriented.
Generalaspnet 1.1 compliant code.
Mohammed Siraj
19:42 30 Mar '05  
I am in need of a very similar validation control. Currently I don't have ASPNET2.0 beta to make use of your code. Do you by any chance have the code for the control written in aspnet1.1 ?

GeneralRe: aspnet 1.1 compliant code.
DanielHac
2:07 31 Mar '05  
The code in this article should be 1.1 compliant.

However I have some easier to use class based validation controls in the zip file, they are 2.0 based. I hope to update this article to show how to use the class based when 2.0 is released.


Last Updated 1 Apr 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010