Dynamic Validation of ASP.NET controls using Javascript/Jquery

I have multiple controls that need validation based on one condition: if one of the three controls have values, the fourth one must also contain a value. I have 4 sets of 4 controls, each numbered from one to four. I've written a quick and dirty function for validation, but it the code itself is unholy and defies most of the principal of good code design, its really ugly.

JavaScript Validation

$(document).ready(function () {
           $("#<%= submitBtn.ClientID%>").click(function () {
            var errorMessage = "";
            var error = false;

            var firstname1 = document.getElementById("<%=child1FN.ClientID%>").value;
            var surname1 = document.getElementById("<%=child1LN.ClientID%>").value;
            var relation1 = document.getElementById("<%=ddlRelationship1.ClientID%>").value;
            var dob1 = document.getElementById("<%=DoB1.ClientID%>");
            if ((firstname1 != "" || surname1 != "" || relation1 != "") && dob1.value == "") {
                errorMessage += "First DoB needs to be filled. \n";
                error=true;
            }

            var firstname2 = document.getElementById("<%=child2FN.ClientID%>").value;
            var surname2 = document.getElementById("<%=child2LN.ClientID%>").value;
            var relation2 = document.getElementById("<%=ddlRelationship2.ClientID%>").value;
            var dob2 = document.getElementById("<%=DoB2.ClientID%>");
            if ((firstname2 != "" || surname2 != "" || relation2 != "") && dob2.value == "") {
                errorMessage += "Second DoB needs to be filled. \n";
                error=true;
            }
            var firstname3 = document.getElementById("<%=child3FN.ClientID%>").value;
            var surname3 = document.getElementById("<%=child3LN.ClientID%>").value;
            var relation3 = document.getElementById("<%=ddlRelationship3.ClientID%>").value;
            var dob3 = document.getElementById("<%=Dob3.ClientID%>");
            if ((firstname3 != "" || surname3 != "" || relation3 != "") && dob3.value == "") {
                errorMessage += "Third DoB needs to be filled. \n";
                error=true;
            }

            var firstname4 = document.getElementById("<%=child4FN.ClientID%>").value;
            var surname4 = document.getElementById("<%=child4LN.ClientID%>").value;
            var relation4 = document.getElementById("<%=ddlRelationship4.ClientID%>").value;
            var dob4 = document.getElementById("<%=DoB4.ClientID%>");
            if ((firstname4 != "" || surname4 != "" || relation4 != "") && dob4.value == "") {
                errorMessage += "Fourth DoB needs to be filled. \n";
                error=true;
            }

            if (error) {
                alert(errorMessage);
                return false;
            }
        });
    });

The problem is, that I cannot use a for loop as asp doesn't accept a javascript value for the following source

<tr>
                 <th>
                        Child one:
                    </th>
                </tr>
                <tr>
                    <td>
                        <asp:TextBox ID="child1FN" runat="server" />
                    </td>
                    <td>
                        <asp:TextBox ID="child1LN" runat="server" />
                    </td>
                    <td>
                        <asp:DropDownList ID="ddlRelationship1" runat="server" ></asp:DropDownList>
                    </td>
                    <td>
                        <telerik:RadDatePicker ID="DoB1" runat="server" Culture="English (Australia)" MinDate="1 Jan 1920" class="datePickerDOB">
                        </telerik:RadDatePicker>
                    </td>
                </tr>

                <tr>
                    <th>
                        Child two:
                    </th>
                </tr>

                <tr>
                    <td>
                        <asp:TextBox ID="child2FN" runat="server" />
                    </td>
                    <td>
                        <asp:TextBox ID="child2LN" runat="server" />
                    <td>
                        <asp:DropDownList ID="ddlRelationship2" runat="server"></asp:DropDownList>
                    </td>
                    <td>
                        <telerik:RadDatePicker ID="DoB2" runat="server" Culture="English (Australia)" MinDate="1 Jan 1920" class="datePickerDOB">
                        </telerik:RadDatePicker>
                    </td>
                </tr> . . .

I've only shown the first two rows of the source which has been simplified and removed styling tags for legibility. Like I wrote; there's 4 rows and they're similar to the above code but with just a different ID.

I was wondering if anybody had any suggestions to improve this code?

Rendered Telerick Code

<span class="riSingle RadInput RadInput_MetroTouch" id="ctl00_cphBody_DoB1_dateInput_wrapper" style="width: 100%; display: block;">
    <input name="ctl00$cphBody$DoB1$dateInput" class="riTextBox riEnabled" id="ctl00_cphBody_DoB1_dateInput" style="padding-left: 2px; font-size: 12px;" type="text">
    <input name="ctl00_cphBody_DoB1_dateInput_ClientState" id="ctl00_cphBody_DoB1_dateInput_ClientState" type="hidden" value='{"enabled":true,"emptyMessage":"","validationText":"","valueAsString":"","minDateStr":"20202020-JanJan-0101-0000-0101-0000","maxDateStr":"99999999-DecDec-3131-0000-1212-0000","lastSetTextBoxValue":""}' autocomplete="off">
</span>

Answers


Giv the container an ID, this will make your life easier with jQuery (and is a little more efficient than using classes etc as selectors). Also, add a class to your "data" rows

<table id="formElements">
     <tr><th>Child 1</th></tr>
     <tr class="data"><!-- Form Elelemt Cells --></tr>
     <!-- etc -->
</table>

Javascript

$(document).ready(function () {
    var formTable = $("#formElements");
    /*console.log(formTable);  */


    $("#submitBtn").click(function (index) {
    var errorMessage = "";
    var error = false;

    //Use the fact we have the elements in a row to our advantage
    $(formTable).find("tr.data").each(function (index) {
        var firstName = $(this).find("td:nth-child(1) input").val();
        var lastName = $(this).find("td:nth-child(2) input").val();
        var relationship = $(this).find("td:nth-child(3) select").val();
        //Taking a punt the value is in the hidden form field for DOB;
        var dob = $(this).find("td:nth-child(4) input[type='hidden']").val();

        //Use console to try and work out what telrik uses to hold the data
        console.log($(this).find("td:nth-child(4) input[type='hidden']"));
        console.log($(this).find("td:nth-child(4) input[type='text']"));

        if ((firstName != "" || lastName != "" || relationship != "") && dob == "") {
            errorMessage += "DoB " + (index + 1) + " needs to be filled. \n";
            error = true;
        }
   });

   if (error) {
       alert(errorMessage);
       return false;
   }
  });
});

This is a little quick and dirty and handling the telrick control could be tricky.

Demo

If you can use ASP.net inbuild validators to validate the telrik control you may be better off using them. Even stil, using a custom ASP.net validator should work in a similar fasion.

Update

I've added a couple of debug lines using console.log to try and help with the telrik controls.

Slighly hacky version

Keep the HTML as per above.

Javascript

$(document).ready(function () {
    var formTable = $("#formElements");
    /*console.log(formTable);  */

    //Create an array of the DatePicker controls
    //You could replace the jQuery selectro with:
    //document.getElementById("<%=DoB1.ClientID%>")
    var arrDoB = new Array( 
                     $("#<%=DoB1.ClientID%>"),
                     $("#<%=DoB2.ClientID%>"),
                     $("#<%=DoB3.ClientID%>"),
                     $("#<%=DoB4.ClientID%>")
                 );

    $("#submitBtn").click(function (index) {
    var errorMessage = "";
    var error = false;

    //Use the fact we have the elements in a row to our advantage
    $(formTable).find("tr.data").each(function (index) {
        var firstName = $(this).find("td:nth-child(1) input").val();
        var lastName = $(this).find("td:nth-child(2) input").val();
        var relationship = $(this).find("td:nth-child(3) select").val();

        //Get the value of the datepicker control from the array
        var dob = arrDoB[index].value;

        if ((firstName != "" || lastName != "" || relationship != "") && dob == "") {
            errorMessage += "DoB " + (index + 1) + " needs to be filled. \n";
            error = true;
        }
   });

   if (error) {
       alert(errorMessage);
       return false;
   }
  });
});

Need Your Help

Reference a value in JavaScript

javascript arrays reference

I have a couple of check boxes that I'd like to use their "name" attribute as the value I reference within my array.

zend : populating a checkbox array with $form->populate(); from controller

php zend-framework checkbox zend-form

We have a zend form with text input fields and array of checkboxes, as shown below -

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.