Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get a ValidationSummary to work with client-side validators?

The .NET ValidationSummary control aggregates error messages from validators that are fired on postback. Is there some way of getting it to also show error messages from client-side validators?

The problem I am working on is that on a long page, it is possible to click a submit button, have some client-side validators fail, but never see the error message. I would like to have a validation summary near the button so that the user is never left without feedback.

I would like any standard .NET validators that have client-side validation to be reflected in the validation summary, but I am most concerned with getting the RequiredFieldValidators to work.

I could hack it so that on clicking the button would automatically, after a short delay, display a general message telling the user to check for errors on the page. This would work for when no postback has occurred, but it would be ugly.

Here is some example code that is not working for me:

<asp:LinkButton ID="btnOpen" runat="server" ToolTip="Open" ValidationGroup="Create" CausesValidation="true" />
<asp:TextBox ID="txtBlah" runat="server" />
<asp:RequiredFieldValidator ID="reqBlah" runat="server" ControlToValidate="txtBlah" EnableClientScript="true" Display="Dynamic" ErrorMessage="Enter some blah" ValidationGroup="Create" />
<asp:ValidationSummary ID="summary" runat="server" EnableClientScript="true" DisplayMode="BulletList" HeaderText="Errors:" ShowMessageBox="true" ShowSummary="true" ValidationGroup="Create" />

The validator shows the error without a postback, but the summary does not.

As has been suggested in the comments, there is probably something else on the page that stops my example code from working. I'm not able to try to reproduce the exact cause right now, though the page is pretty heavy and has some UpdatePanels on there, so I'll just stick with my hack until there is more time to work on it.

Thanks for the attempts to help. I recommend people not to work on this question any more, as I don't think I've provided enough info to really help anyone solve the issue.

like image 911
David Avatar asked Dec 07 '09 00:12

David


2 Answers

I too have had this problem. After spending way too much time dissecting the MS client side validation API ;), I traced the problem to a weird issue with DOM parsing, below I explain why this happens in some cases and the solution I used to fix it.

[Why does it happen?]

Each validator control is rendered as a span with non-standard attributes that are used to perform the client side validation. For example the evaluationfunction attribute below:

<span id="...id" controltovalidate="...BillingName" errormessage="blah" evaluationfunction="RequiredFieldValidatorEvaluateIsValid" display="Dynamic" initialvalue="" >*</span>

These attributes are parsed by the framework in the API like this below (notice the eval):

for (i = 0; i < Page_Validators.length; i++) {
  val = Page_Validators[i];
  if (typeof(val.evaluationfunction) == "string") {
     eval("val.evaluationfunction = " + val.evaluationfunction + ";");
     } 
}

the problem is that the special attributes i.e. evaluationfunction we're always returning undefined so the string was never converted to a proper validator object. This to me is still a mystery because from what I can tell it appears to be totally random.

What happens is when the Page_ClientValidate is kicked off, it tries to invoke each validators validate function but it can't because evaluationfunction == undefined. Instead of using false as the default it assumes true and so no validation actually happens and everything appears valid from the client side. the if (typeof(val.evaluationfunction) == "function") is never true so it falls back on the prior assignment of val.isvalid = true;.

function ValidatorValidate(val, validationGroup, event) {
 val.isvalid = true;
 if ((typeof(val.enabled) == "undefined" || val.enabled != false) && IsValidationGroupMatch(val, validationGroup)) 
 {
  if (typeof(val.evaluationfunction) == "function") 
  {
   val.isvalid = val.evaluationfunction(val);
   if (!val.isvalid && Page_InvalidControlToBeFocused == null && typeof(val.focusOnError) == "string" && val.focusOnError == "t") 
   {
    ValidatorSetFocus(val, event);
   }
  }
 }
  ValidatorUpdateDisplay(val);
} 

[How did I fix it?]

To fix this I wrote a routine that can be called after the DOM has finished loading. This routine loops all of the validator controls and tries to create the object properties from the raw markup data in the SPAN using JQuery, although you could probably use any other equivalent tool to get the same result. This routine does not fix all of the validator controls, mainly required field validators and regular expression validators. You'll need to change it if your using other validation controls that have additional properties.

function fixValidatorProperties()
{
    if (Page_Validators && Page_Validators[0] && Page_Validators[0].evaluationfunction == undefined)
    {
        var val = null;
        for (i = 0; i < Page_Validators.length; i++) 
        {
            val = Page_Validators[i];

            if (val.initialvalue == undefined)
                val.initialvalue = "";

            if ($(val).attr("evaluationfunction"))
                  eval("val.evaluationfunction = " + $(val).attr("evaluationfunction") + ";");
            if ($(val).attr("controltovalidate"))
                  val.controltovalidate = $(val).attr("controltovalidate");
            if ($(val).attr("errormessage"))
                  val.errormessage = $(val).attr("errormessage");
            if ($(val).attr("Dynamic"))
                  val.Dynamic = $(val).attr("Dynamic");     
            if ($(val).attr("initialvalue"))
                  val.initialvalue = $(val).attr("initialvalue"); 
                if ($(val).attr("ValidationExpression"))  
                  val.validationexpression =  $(val).attr("ValidationExpression");
         }     
    }
}
like image 137
James Avatar answered Oct 19 '22 23:10

James


I have decided to implement a bit of a hack instead, which is to use JQuery to set up a click handler which detects if there are any errors on the page, and just displays a general message telling the user to find and fix the errors. It's not good, but it will do for now.

like image 45
David Avatar answered Oct 19 '22 23:10

David