jump to navigation

Change Background Color of Invalid Controls (ASP.NET Validator) September 16, 2009

Posted by codinglifestyle in ASP.NET, CodeProject.
Tags: , , , ,
trackback

I was working with a customer who has invested a lot in redoing the validation in their web application.  I accedentially suggested wouldn’t it be nice if we could change the background or border of the field in question.  The customer loved this idea which meant I’d just created more work for myself.  After searching about I wasn’t finding this done for me, so I actually had to write some code instead of cutting and pasting.

If you set a breakpoint on WebForm_OnSubmit and step in you can check out the .NET validator script.  Key thing here is a global array called Page_Validators.  From here it is fairly trivial to test and change something about the control in question.

function fnOnUpdateValidators()

{

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.isvalid)

ctrl.style.background=“#FFAAAA”;

else

ctrl.style.backgroundColor = “”;

}

}

}

 

Of course, one problem is if the control already had a background color, it would be lost.  This can be circumvented by storing the old value in an attribute or elsewhere.  Also, custom validators are a special case so you will need to add the appropriate changes for fields validated in a custom way.

To make sure my function is called I use the deprecated Page.RegisterOnSubmitStatement(“val”, “fnOnUpdateValidators();”).  This will call my function after the validators have fired so the isvalid is up to date.

Comments»

1. Sil - September 21, 2009

I have founds a more elegant way of reaching the same result:

var OriginalValidatorUpdateDisplay = null;

function NewValidatorUpdateDisplay(val) {
OriginalValidatorUpdateDisplay(val);
if (val.controltovalidate) {
document.getElementById(val.controltovalidate).style.backgroundColor = val.isvalid ? ” : ‘#FFAAAA’;
}
}

if (typeof (ValidatorUpdateDisplay) == ‘function’) {
OriginalValidatorUpdateDisplay = ValidatorUpdateDisplay;
ValidatorUpdateDisplay = NewValidatorUpdateDisplay;
}

This way the background color is also updated when the value of the control is changed, instead of only when the form is submitted.

codinglifestyle - September 22, 2009

Just to comment on Sil’s post, we can see the last few lines of his code are executed at startup. What he is doing is storing Microsoft’s function ValidatorUpdateDisplay in a global variable and replacing it with our own. Our version, NewValidatorUpdateDisplay calls the old version and then executes our custom code to change the background color. Great work!

A caveat to this is currently ValidatorUpdateDisplay is not reliably called if you are doing anything funny (like pressing a button which inserts a value to a textbox with a required field validator… the background color won’t dynamically change in this instance). Also, be mindful that if you have multiple validators on the same field my code and Sil’s code will clobber the previous validator. For example, one may be a regular expression validator which fails and the next is a required field validator which passes. In this case, the field will appear to be valid as the required field validator clobbered the regular expression validator.

Big Dave - April 13, 2010

That is brilliant, works great in my forms.

The only issue I have is for textbox controls that have multiple validators (i.e for a qty I would have a required field validator, compare validator to check entry is a number and a range validator so can’t order too many) the validators further down cancel out the background colour (i.e. i enter nothing and it does turn red because nothing entered but if i then include the other validators after, because there is nothing to validate they show it as valid so clear the red background).

Any thoughts about fixing this small issue or work around with validators?

2. techron - October 6, 2009

Awesome! Much better than some of the code behind stuff I’ve seen around to do this.
To prevent the clobbering of multiple validators on a field, maybe you can test the type of validator before attaching the new event. Or just check an array of validators (ids) and only attach the new event if it matches.

3. Lester Espinosa Martinez - May 8, 2010

All was excellent, only one question:

Where I put this code?

4. Markus Wagner - May 20, 2010

Very helpful!
To fix the problem with more than one validator, I chnaged the code a little bit:

if (val.controltovalidate) {
var control = document.getElementById(val.controltovalidate);
if (control != null) {
control.style.backgroundColor =
CheckValidatorsForControl(control) ? ” : ‘#FFAAAA’;
}
}

Instead of calling val.isvalid I call the function CheckValidatorsForControl() which checks all validators for the control:

function CheckValidatorsForControl(control) {
for (var i = 0; i < control.Validators.length; i++) {
if (!control.Validators[i].isvalid) {
return false;
}
}
return true;
}

Markus Wagner - May 20, 2010

After settings the backgroundColor of the control I also added

ValidatorUpdateIsValid();
ValidationSummaryOnSubmit(val.validationGroup);

The first call sets the property Page_IsValid. And the second one generates the corresponding ValidationSummary. However, this is only useful, if you set ShowMessageBox to false.

5. Harry Wang - June 23, 2010

Markus: Could you please provide a working sample for your code? For a beginner, I do not know how to call the function you provided. Thanks.

6. ASP.Net Javascript Validation Highlighting Controls « the don blog - September 27, 2010

[…] this would be easy, I quickly asked Google how I could do it and found very little. I did find this post, which was very helpful, but a bit incomplete. I did adapt the code I found there and put together […]

7. Thought might be usefull to some one. - January 9, 2013

function arrAdd(arr, value) {
arr.push(value);
}
/**
* Array.prototype.[method name] allows you to define/overwrite an objects method
* needle is the item you are searching for
* this is a special variable that refers to “this” instance of an Array.
* returns true if needle is in the array, and false otherwise
*/
Array.prototype.contains = function (needle) {
for (i in this) {
if (this[i] == needle) return true;
}
return false;
}
function fnOnUpdateValidators() {
var ctrlArr = Array();
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.isvalid) {
if (!ctrlArr.contains(val.controltovalidate))
ctrlArr.push(val.controltovalidate);
ctrl.className = "errorvalidator";
}
else {

if (!ctrlArr.contains(val.controltovalidate))
ctrl.className = "";
}
}
}
}

8. Ajaypravin - June 16, 2014

Nice article…!!


Leave a comment