To read the article online, visit http://www.4GuysFromRolla.com/articles/121907-1.aspx

Disabling the Submit Button Until a CheckBox is Checked

By Scott Mitchell


Introduction


ASP.NET provides a variety of validation Web controls that can be used to validate a user's form field inputs. Unfortunately, the validation Web controls do not work with the CheckBox or CheckBoxList Web controls. In a previous article, Creating Validator Controls for the CheckBox and CheckBoxList, I shared two custom controls I had created to address this shortcoming: CheckBoxValidator and CheckBoxListValidator. These controls work like any other ASP.NET validation control - at a minimum, just add them to a page and specify their ControlToValidate and ErrorMessage properties.

A colleague recently asked me to enhance the CheckBoxValidator control's client-side script so that it could optionally disable a particular button when invalid. In particular, she wanted to be able to specify the ID of a Button control in the CheckBoxValidator's properties. The CheckBoxValidator would then use client script to disable (gray out) the Button when the CheckBoxValidator was invalid. The following screen shot illustrates this concept. On the left, the CheckBox is unchecked so the Submit button is grayed out; on the right, the CheckBox has been checked so the Button has become enabled.

The submit button is disabled when the CheckBox is unchecked.

I recently updated the CheckBoxValidator to meet these specifications. Read on to learn more about this new enhancement to the CheckBoxValidator!

Before You Read This Article...
The CheckBoxValidator is a custom validation control I created and shared in the Creating Validator Controls for the CheckBox and CheckBoxList article. Since this article builds on the code discussed in Creating Validator Controls for the CheckBox and CheckBoxList, I encourage you read the previous article before starting on this one.

A Quick Overview of the CheckBoxValidator Control


Before we look at the new features of the CheckBoxValidator, let's take a moment to quickly review the core CheckBoxValidator functionality. The CheckBoxValidator was designed to ensure that a CheckBox is either checked or unchecked. To use the control, you simply add it to a page and type in the ID of the CheckBox to validate into its ControlToValidate property. The CheckBoxValidator injects client-side script into the page to perform client-side validation in addition to its server-side validation.

By default, the CheckBoxValidator will only report that the data is valid if its CheckBox is checked. If you want to CheckBoxValidator to report valid data if its CheckBox is unchecked, then set the validator control's MustBeChecked property to False.

That's all there is to it! Using the CheckBoxValidator is extremely easy.

Adding a AssociatedButtonControlId Property to the CheckBoxValidator Class


In order to update the CheckBoxValidator to disable an associated Button control when invalid, we need to add a public property to the CheckBoxValidator class that enables the page developer to optionally specify the associated button control. To capture this information I created a public property named AssociatedButtonControlId and a protected property named AssociatedButton. The page developer using the CheckBoxValidator sets the AssociatedButtonControlId property to the ID of the Button, LinkButton, or ImageButton control on the page that he wants to have disabled when the CheckBoxValidator is reporting invalid data. The AssociatedButton property is used internally in the CheckBoxValidator code; it returns a reference to the Button, LinkButton, or ImageButton Web control referenced by the AssociatedButtonControlId.

public string AssociatedButtonControlId
{
   get
   {
      object o = ViewState["AssociatedButtonControlId"];
      if (o == null)
         return string.Empty;
      else
         return (string)o;
   }
   set
   {
      ViewState["AssociatedButtonControlId"] = value;
   }
}

private WebControl _associatedButton = null;
protected WebControl AssociatedButton
{
   get
   {
      if (_associatedButton == null && !string.IsNullOrEmpty(this.AssociatedButtonControlId))
         _associatedButton = FindControl(this.AssociatedButtonControlId) as WebControl;

      return _associatedButton;
   }
}

As you can see by the above code, the AssociatedButtonControlId property is of type string and serializes its value to the ViewState collection. The AssociatedButton property simply returns a reference to the WebControl referenced by AssociatedButtonControlId (if it is set). If AssociatedButtonControlId is not set or there is no control with that ID found, the AssociatedButton property returns null. (For more information on why the AssociatedButtonControlId property serializes its value to view state, be sure to read: Understanding ASP.NET View State.)

Verifying the AssociatedButtonControlId Property Value


The BaseValidator class, from with which all ASP.NET validator controls derive, contains a protected ControlPropertiesValid method that is called during the page's life cycle to ensure that the validation control's properties are set to acceptable values. The built-in validation controls use this method to ensure that a value for the required ControlToValidate property is set and that it references a valid control on the page. The CheckBoxValidator overrides this method and ensures that the the ControlToValidate property references a CheckBox control.

I added the following code to this method to ensure that if the AssociatedButtonControlId property is set that it refers to a valid Button, LinkButton, or ImageButton control. If the property is set, but does reference a control, or if its set but does not reference a Button, LinkButton, or ImageButton control, an HttpException is raised.

protected override bool ControlPropertiesValid()
{
   ... Previous checks removed for brevity ...

   // Make sure AssociatedButton, if set, referenced a Button, LinkButton, or ImageButton         
   bool btnCtrlIdSetButNoRef = (!string.IsNullOrEmpty(this.AssociatedButtonControlId) && this.AssociatedButton == null);
   
   bool btnCtrlIdNotRefButton = false;
   if (AssociatedButton != null)
   {
      if (AssociatedButton is Button || AssociatedButton is LinkButton || AssociatedButton is ImageButton)
         // No problem here...
         btnCtrlIdNotRefButton = false;
      else
         // AssociatedButton is an invalid type
         btnCtrlIdNotRefButton = true;
   }

   if (btnCtrlIdSetButNoRef || btnCtrlIdNotRefButton)
      throw new HttpException(string.Format("The AssociatedButtonControlId property of '{0}', if set, must reference a Button, LinkButton, or ImageButton control.", this.ID));


   return true;   // if we reach here, everything checks out
}

Adding Client-Side Script to Enable and Disable the Associated Button


If there is a button associated with the CheckBoxValidator then we need to inject some client-side script to enable or disable the button as the CheckBox's checked state changes. To accomplish this, I created a JavaScript function named CheckBoxValidatorDisableButton that takes in three input parameters: chkId, the client-side id of the CheckBox; mustBeChecked, a Boolean value indicating whether the CheckBox must be checked in order for it to be valid; and btnId, , the client-side id of the CheckBoxValidator's associated button. This method references the checkbox and button and disables the button if the checkbox's checked state is something other than the "correct" check state (as noted by the mustBeChecked input parameter).

function CheckBoxValidatorDisableButton(chkId, mustBeChecked, btnId)
{
   var button = document.getElementById(btnId);
   var chkbox = document.getElementById(chkId);
   
   if (button && chkbox)
   {
      button.disabled = (chkbox.checked != mustBeChecked);
   }
}

This JavaScript function is included in the skmValidators.js file, which, at compile time, is embedded in the skmValidators assembly. The CheckBoxValidator and CheckBoxValidatorList controls already contain code that adds a reference to this JavaScript file in the rendered page output. For more information on this, refer to Creating Validator Controls for the CheckBox and CheckBoxList and Accessing Embedded Resources through a URL using WebResource.axd.

With this JavaScript function in place, all that remains is to call it when the CheckBox's checked state changes and when the page is loaded (so that the associated button is enabled or disabled based on the CheckBox's checked state after the browser has loaded the page). This is accomplished in the CheckBoxValidator's OnPreRender method. The following code first adds a reference in the page to the necessary JavaScript file (skmValidation.js). Next, it defines the syntax for the CheckBoxValidatorDisableButton function call and then associates that syntax with the CheckBox's client-side onclick event and when the page finishes loading.

protected override void OnPreRender(EventArgs e)
{
   base.OnPreRender(e);

   if (this.RenderUplevel && this.Page != null)
   {
      // Register the client-side function using WebResource.axd (if needed)
      // see: http://aspnet.4guysfromrolla.com/articles/080906-1.aspx
      if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(this.GetType(), "skmValidators"))
         this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "skmValidators", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "skmValidators.skmValidators.js"));

      // If there's an associated Button for this validator, add the script to enable/disable
      // it when the checkbox is clicked AND when the page is first loaded
      if (this.AssociatedButton != null)
      {
         string callCheckBoxValidatorDisableButton = string.Format("CheckBoxValidatorDisableButton('{0}', {1}, '{2}');", this.CheckBoxToValidate.ClientID, MustBeChecked ? "true" : "false", this.AssociatedButton.ClientID);

         this.CheckBoxToValidate.Attributes.Add("onclick", callCheckBoxValidatorDisableButton);

         this.Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), callCheckBoxValidatorDisableButton, true);
      }

   }
}

Using the CheckBoxValidator's New Feature


To have the CheckBoxValidator interactively enable and disable a specified Button, LinkButton, or ImageButton control, simply:
  1. Add a CheckBoxValidator to the page,
  2. Set its ControlToValidate property to the ID of the CheckBox on the page whose check state you want to validate, and
  3. Set its AssociatedButtonControlId property to the ID of the Button, LinkButton, or ImageButton that you want to have enabled or disabled depending on the CheckBox's checked state.
That's all there is to it!

The download at the end of this article includes the complete source code to the CheckBoxValidator and CheckBoxListValidator controls, along with a simple ASP.NET demo website showing how to use these two validation controls (including an example illustrating the AssociatedButtonControlId property).

Conclusion


In this article we looked at how to extend the CheckBoxValidator control to include the ability to enable or disable a corresponding Button, LinkButton, or ImageButton control, based on the corresponding CheckBox's checked state. This involved adding a new property to the CheckBoxValidator class, updating the skmValidators.js JavaScript to add a new JavaScript function for enabling or disabling the associated button, and calling this new JavaScript function when the associated CheckBox is checked (or unchecked) and when the web page loads in the browser.

Happy Programming!

  • By Scott Mitchell


    Further Readings:

  • Validating User Input in ASP.NET Web Pages
  • Form Validation with ASP.NET - It Doesn't Get Any Easier!
  • Dissecting Validation Controls in ASP.NET 2.0
  • Accessing Embedded Resources through a URL using WebResource.axd
  • Creating Validator Controls for the CheckBox and CheckBoxList
  • Attachments


  • Download the skmValidator Controls and a Demo Website Application (in ZIP format)
  • Article Information
    Article Title: ASP.NET.Disabling the Submit Button Until a CheckBox is Checked
    Article Author: Scott Mitchell
    Published Date: December 19, 2007
    Article URL: http://www.4GuysFromRolla.com/articles/121907-1.aspx


    Copyright 2014 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers