Archive
Change Background Color of Invalid Controls with ASP.NET Validators
Chris posted an excellent article explaining how to change background color of invalid controls (with ASP.NET Validators). In his article, the code loops through each validator in Page_Validators (it’s a global array in Javascript), finds the control to validate (ctrl.controltovalidate) of the validator, changes the background color of the control if the valiator is in invalid mode (ctrl.isvalid == false).
As the updates of validators only happens when the form is submitted, but I need a bit more – I want the updates trigger whenever the user makes change to the controls (type text in the text box, change option in the select box, etc). Using bind() function in jQuery will do the trick.
Here is the code:
<script type=”text/javascript”>
var g_BackgroundColor = “#FFAAAA”;
jQuery(document).ready(function() {
for (var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
if (validator.controltovalidate) {
BindValidatorsForChecking(validator.controltovalidate);
}
}
});
function OnUpdateValidators() {
for (var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
// *** For each validator, find its associated control, then check its valid status
if (validator.controltovalidate) {
var control = document.getElementById(validator.controltovalidate);
if (control != null) {
control.style.backgroundColor = CheckValidatorsForControl(control) ? ” : g_BackgroundColor;
// *** Bind to check valid status
BindValidatorsForChecking(validator.controltovalidate);
}
}
}
}
// *** Check all validators for a control
function CheckValidatorsForControl(control) {
for (var i = 0; i < control.Validators.length; i++) {
if (!control.Validators[i].isvalid) {
return false;
}
}
return true;
}
// *** Bind to check valid status
function BindValidatorsForChecking(controlID) {
jQuery(“#” + controlID).bind(“blur focus mouseout mouseleave”, function(e) {
this.style.backgroundColor = CheckValidatorsForControl(this) ? ” : g_BackgroundColor;
});
}
</script>
In the code behind, you will need to hook the updates when the form is submitted as well:
Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), “OnUpdateValidators_Key”, “OnUpdateValidators();”);
jQuery and ASP.NET AJAX PageMethods
In ASP.NET AJAX there are two ways to make AJAX calls to retrieve data from server side – Web Services and Page Methods. For the project I am working on, based on the design and flexibility for page developers, I use PageMethods to query data from the server side and it worked well. But there is one minor issue with PageMethods – you can’t assign Javascript inner functions for the success and error callbacks. It’s not a big deal, but I like the way that Google Map uses closures. So I searched for alternatives and I found jQuery has the ajax() function which is what I need.
Here I build two pages – one uses PageMethods, another used jQuery – for comparison of the syntax and usage.
I use two basic container classes for my data passed between client and server:
using System;
namespace Posts
{
[Serializable]
public class LatLong
{
public double? latitude;
public double? longitude;
}
}
using System;
namespace Posts
{
[Serializable]
public class MapView
{
public LatLong center;
public int? zoom;
}
}
The MapViewData class provides a static method to generate random map view data:
using System;
using System.Collections;
using System.Collections.Generic;
namespace Posts
{
public class MapViewData
{
public const double DefaultLatitude = 49.266214d;
public const double DefaultLongitude = -122.998577d;
public const int DefaultZoom = 12;
public static List<MapView> GenerateMapViewData(int count)
{
List<MapView> data = new List<MapView>();
Random rand = new Random();
for (int i = 0; i < count; i++)
{
double delta = rand.NextDouble() * 0.001d;
LatLong latlong = new LatLong();
latlong.latitude = DefaultLatitude + delta;
latlong.longitude = DefaultLongitude + delta;
MapView view = new MapView();
view.center = latlong;
view.zoom = DefaultZoom;
data.Add(view);
}
return (data);
}
}
}
The following static page method is in both ASP.NET AJAX and jQuery pages for return a collection of MapView objects to Javascript:
[WebMethod]
public static List<MapView> GetMapViewData(int count)
{
return (MapViewData.GenerateMapViewData(count));
}
The first example is the ASP.NET AJAX with PageMethods. Couple things to notice:
- EnablePageMethods=”true” in the ScriptManger – to enable the static page methods in ASP.NET page can be called from Javascript.
- In success_callback, the result is the collection of MapView objects. We can loop through the collection and access properties of each object.
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Compare1.aspx.cs” Inherits=”Posts.Compare1″ %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>ASP.NET AJAX</title>
<script type=”text/javascript”>
function get_mapview_data(count)
{
PageMethods.GetMapViewData(
count,
success_callback,
error_callback
);
}
function success_callback(result, context, method)
{
var sb = new Sys.StringBuilder();
for (var i in result) {
sb.append(“center -> (“ + result[i].center.latitude + “, “ + result[i].center.longitude + “), “);
sb.append(“zoom -> “ + result[i].zoom);
sb.append(“<br/>”);
}
$get(“mapview_data”).innerHTML = sb.toString();
}
function error_callback(error, context, method)
{
$get(“mapview_data”).innerHTML = “Error –> “ + error.get_message();
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<asp:ScriptManager ID=”ScriptManager1″ runat=”server” EnablePageMethods=”true” />
<div>
<a href=”javascript:get_mapview_data(20);”>Get MapView data</a>
</div>
<br />
<div id=”mapview_data”></div>
</form>
</body>
</html>
The second example isjQuery with PageMethods. Couple things to notice too:
- The URL to request is the current page URL concatenated with “/PageMethodName”.
- I use JSON2 Javascript library to parse (deserialize) the XmlHttpRequest object returned in the error callback. You can use Sys.Serialization.JavaScriptSerializer.deserialize() to do the same thing here.
- There is no need to use ScriptManager.
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Compare2.aspx.cs” Inherits=”Posts.Compare2″ %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>jQuery</title>
<script type=”text/javascript” src=”/JavaScript/jquery-1.2.6.min.js”></script>
<script type=”text/javascript” src=”/JavaScript/json2.js”></script>
<script type=”text/javascript”>
function get_mapview_data(count)
{
$.ajax({
type: “POST”,
url: window.location.href + “/GetMapViewData”,
data: “{\”count\”:\”" + count + “\”}”,
contentType: “application/json; charset=utf-8″,
dataType: “json”,
success: function(xhr, status) {
var sb = “”;
for (var i in xhr) {
sb += “center -> (“ + xhr[i].center.latitude + “, “ + xhr[i].center.longitude + “), “;
sb += “zoom -> “ + xhr[i].zoom;
sb += “<br/>”;
}
$(“#mapview_data”).html(sb);
},
error: function(xhr, status, error) {
var err = JSON.parse(xhr.responseText);
$(“#mapview_data”).html(“Error –> “ + err.Message);
}
});
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<a href=”javascript:get_mapview_data(20);”>Get MapView data</a>
</div>
<br />
<div id=”mapview_data”></div>
</form>
</body>
</html>
I use Firebug to check the Post and Response in both XmlHttpRequests, they are the same in both pages.


