Saturday, May 09, 2009

Adding custom client side validation to controls inside GridView

Some times we find it necessary to provide custom validation to controls inside a GridView.
Recently I had to have a DropDownList for selecting a country inside a gridview, the country dropdownlist contains several items including an item with the text "Other". When "Other" is selected, a textbox should show up where in the user can provide the rationale for selecting "Other". Also, I had to make sure that the textbox is not left blank when "Other" is selected.

To Recap
Requirements:
Make sure that a value is selected from the country dropdownlist.
When "Other" is selected for country, show a textbox to show enter what the "Other" country is
Make sure that a value is entered in the textbox when "Other" is selected

First the GridView, for simplicity I'm just showing the country dropdownlist and the TextBox. Both those controls are included in a templatefield in the GridView
Leaving out the databinding details.


I also add an eventhandler for OnRowDataBound event.


<asp:GridView ID="grdSales" runat="server" OnRowDataBound="grdSales_RowDataBound"
ShowFooter="true">
<Columns>
<asp:TemplateField HeaderText="Country">
<ItemTemplate>
<asp:RequiredFieldValidator runat="server" ID="reqValCountry" ControlToValidate="ddlCountry"
Display="Dynamic" ErrorMessage="Country is required<br>" ValidationGroup="Country"></asp:RequiredFieldValidator>
<asp:DropDownList ID="ddlCountry" runat="server">
<asp:ListItem Value=""> --Select Country--</asp:ListItem>
<asp:ListItem Value="1">USA</asp:ListItem>
<asp:ListItem Value="2">Canada</asp:ListItem>
<asp:ListItem Value="3">Mexico</asp:ListItem>
<asp:ListItem Value="4">Other</asp:ListItem>
</asp:DropDownList>
<asp:Panel ID="pnlOther" Style="display: none" runat="server">
Other:&nbsp;<asp:TextBox runat="server" ID="txtOther"></asp:TextBox>
<asp:CustomValidator ID="custValCountry" runat="server" ValidationGroup="Country"
ControlToValidate="ddlCountry" ClientValidationFunction="ValidateCountry"
ErrorMessage="Other is required"></asp:CustomValidator>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

To meet the first requirement add a required field validator to ddlCountry drowdownlist.
For the second requirement, I need to add an onchange Event to the dropdownlist. In the event handler, I want to inspect the value selected and show the panel that contains the text box.
For the third requirement, I added a custom validator which calls a javascript function ValidateCountry.

Inside the grdCountry_RowDataBound event handler, pass the appropriate ids of the controls to the javascript functions.


protected void grdSales_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType != DataControlRowType.DataRow) return;

DropDownList ddl = e.Row.FindControl("ddlCountry") as DropDownList;
Panel pnl = e.Row.FindControl("pnlOther") as Panel;
TextBox txt = e.Row.FindControl("txtOther") as TextBox;
CustomValidator val = e.Row.FindControl("custValCountry") as CustomValidator;

if (ddl == null || pnl == null || txt == null || val == null) return;

//Add an onchange event to the ddlCountry drop down list which is in each data row of the grid view
//The javascript function will take as parameters Ids of the drop down list and the div that should be shows/hid

string jsToggle = "TogleCountry('" + ddl.ClientID + "','" + pnl.ClientID + "')";
ddl.Attributes.Add("onchange", jsToggle);

//The custom validation control will validate the drop down list. If option Other is selcted, it checks
//if the txtOther has some text
//Here we are adding ids of the ddlCountry and txtOther as client attributes of the validation control
//These attributes can be accessed from the client side function to help in doing the custom validation
val.Attributes.Add("ddl", ddl.ClientID);
val.Attributes.Add("txt", txt.ClientID);
}

Finally the javascript functions
I'm using ASP.net AJAX client side library here. If you are not using ASP.net AJAX just replace $get with document.getElementById

function TogleCountry(ddl, div) {
var selectedIndex = $get(ddl).selectedIndex;
$get(div).style.display = 'none';
if (selectedIndex == 5)
$get(div).style.display = 'block';
}


function ValidateCountry(sender, args) {
var ddl = sender.attributes["ddl"].value; //These attributes are added to the validator in the rowdatabound event of the GridView
var txt = sender.attributes["txt"].value;

var selectedIndex = $get(ddl).selectedIndex;
var txtOther = $get(txt).value;

if (selectedIndex == 4 && txtOther.length < isvalid =" false;" isvalid =" true;">

Digg It! Add to del.icio.us Stumble This

1 Comment:

๑۩۞۩๑ √іИςЄ ๑۩۞۩๑ said...

It seems that in the "ValidateCountry" javascript function some lines of code are missing.
It would be very useful if you could post a complete example using an XML as data.
I can use standard client side validators in a grid view when editing while custom validators don't fire validation event.

Thanks in advance,
Vince