ToggleButtonExtender

March 15, 2026 · View on GitHub

The ToggleButtonExtender replaces a target checkbox with a clickable image that toggles between checked and unchecked states. It supports separate images for checked, unchecked, hover, and disabled states, providing a visually rich alternative to standard checkboxes.

Original Ajax Control Toolkit documentation: https://www.asp.net/ajax/ajaxcontroltoolkit/ToggleButtonExtender

Features Supported in Blazor

  • TargetControlID — ID of the checkbox to enhance with toggle image behavior
  • ImageWidth — Width of the toggle image in pixels
  • ImageHeight — Height of the toggle image in pixels
  • UncheckedImageUrl — Image URL for the unchecked state
  • CheckedImageUrl — Image URL for the checked state
  • UncheckedImageAlternateText — Alt text for the unchecked image
  • CheckedImageAlternateText — Alt text for the checked image
  • CheckedImageOverUrl — Hover image URL when checked
  • UncheckedImageOverUrl — Hover image URL when unchecked
  • DisabledUncheckedImageUrl — Image URL when disabled and unchecked
  • DisabledCheckedImageUrl — Image URL when disabled and checked
  • Enabled — Enable or disable the extender behavior
  • BehaviorID — Optional identifier for JavaScript behavior lookup

Web Forms Syntax

<asp:CheckBox ID="chkSubscribe" runat="server" />

<ajaxToolkit:ToggleButtonExtender
    ID="tbe1"
    runat="server"
    TargetControlID="chkSubscribe"
    ImageWidth="24"
    ImageHeight="24"
    UncheckedImageUrl="~/images/toggle-off.png"
    CheckedImageUrl="~/images/toggle-on.png"
    UncheckedImageAlternateText="Not subscribed"
    CheckedImageAlternateText="Subscribed"
    CheckedImageOverUrl="~/images/toggle-on-hover.png"
    UncheckedImageOverUrl="~/images/toggle-off-hover.png" />

Blazor Migration

<CheckBox ID="chkSubscribe" />

<ToggleButtonExtender
    TargetControlID="chkSubscribe"
    ImageWidth="24"
    ImageHeight="24"
    UncheckedImageUrl="/images/toggle-off.png"
    CheckedImageUrl="/images/toggle-on.png"
    UncheckedImageAlternateText="Not subscribed"
    CheckedImageAlternateText="Subscribed"
    CheckedImageOverUrl="/images/toggle-on-hover.png"
    UncheckedImageOverUrl="/images/toggle-off-hover.png" />

Migration is simple: Remove the ajaxToolkit: prefix and runat="server". Update image paths from ~/ to /. Everything else stays the same!

Properties Reference

PropertyTypeDefaultDescription
TargetControlIDstring(required)ID of the checkbox to enhance with toggle image behavior
ImageWidthint0Width of the toggle image in pixels
ImageHeightint0Height of the toggle image in pixels
UncheckedImageUrlstring""URL of the image displayed when the checkbox is unchecked
CheckedImageUrlstring""URL of the image displayed when the checkbox is checked
UncheckedImageAlternateTextstring""Alternate text for the unchecked image (accessibility)
CheckedImageAlternateTextstring""Alternate text for the checked image (accessibility)
CheckedImageOverUrlstring""URL of the image displayed on hover when checked
UncheckedImageOverUrlstring""URL of the image displayed on hover when unchecked
DisabledUncheckedImageUrlstring""URL of the image displayed when disabled and unchecked
DisabledCheckedImageUrlstring""URL of the image displayed when disabled and checked
BehaviorIDstringTargetControlIDOptional identifier for JavaScript behavior lookup
EnabledbooltrueWhether the extender is active

Usage Examples

Basic Toggle Button

@rendermode InteractiveServer

<CheckBox ID="chkNotifications" />

<ToggleButtonExtender
    TargetControlID="chkNotifications"
    ImageWidth="48"
    ImageHeight="24"
    UncheckedImageUrl="/images/switch-off.png"
    CheckedImageUrl="/images/switch-on.png"
    UncheckedImageAlternateText="Notifications off"
    CheckedImageAlternateText="Notifications on" />

Toggle with Hover States

@rendermode InteractiveServer

<CheckBox ID="chkFavorite" />

<ToggleButtonExtender
    TargetControlID="chkFavorite"
    ImageWidth="32"
    ImageHeight="32"
    UncheckedImageUrl="/images/star-empty.png"
    CheckedImageUrl="/images/star-filled.png"
    UncheckedImageOverUrl="/images/star-empty-hover.png"
    CheckedImageOverUrl="/images/star-filled-hover.png"
    UncheckedImageAlternateText="Add to favorites"
    CheckedImageAlternateText="Remove from favorites" />

Toggle with Disabled States

@rendermode InteractiveServer

<CheckBox ID="chkFeature" Enabled="false" />

<ToggleButtonExtender
    TargetControlID="chkFeature"
    ImageWidth="48"
    ImageHeight="24"
    UncheckedImageUrl="/images/toggle-off.png"
    CheckedImageUrl="/images/toggle-on.png"
    DisabledUncheckedImageUrl="/images/toggle-off-disabled.png"
    DisabledCheckedImageUrl="/images/toggle-on-disabled.png" />

HTML Output

The ToggleButtonExtender produces no HTML itself — it attaches JavaScript behavior that replaces the checkbox's visual appearance with an image element while preserving the checkbox's checked/unchecked state.

JavaScript Interop

The ToggleButtonExtender loads toggle-button-extender.js as an ES module. JavaScript handles:

  • Hiding the original checkbox and displaying an image in its place
  • Swapping images on click (checked ↔ unchecked)
  • Swapping images on hover (over states)
  • Displaying disabled images when the checkbox is disabled
  • Keeping the underlying checkbox state in sync

Render Mode Requirements

The ToggleButtonExtender requires InteractiveServer render mode:

@rendermode InteractiveServer

Graceful Degradation

  • SSR/Static mode: The extender silently skips initialization. The standard checkbox is displayed.
  • JavaScript disabled: Same as SSR — standard checkbox functions normally.

Migration Notes

From Web Forms Ajax Toolkit

  1. Remove ajaxToolkit: prefix

    - <ajaxToolkit:ToggleButtonExtender
    + <ToggleButtonExtender
    
  2. Remove runat="server" and ID attributes

  3. Update image paths from ~/ syntax to / paths

    - UncheckedImageUrl="~/images/toggle-off.png"
    + UncheckedImageUrl="/images/toggle-off.png"
    

Before (Web Forms)

<asp:CheckBox ID="chkAgree" runat="server" />

<ajaxToolkit:ToggleButtonExtender
    ID="tbe1"
    TargetControlID="chkAgree"
    ImageWidth="24"
    ImageHeight="24"
    UncheckedImageUrl="~/images/unchecked.png"
    CheckedImageUrl="~/images/checked.png"
    runat="server" />

After (Blazor)

<CheckBox ID="chkAgree" />

<ToggleButtonExtender
    TargetControlID="chkAgree"
    ImageWidth="24"
    ImageHeight="24"
    UncheckedImageUrl="/images/unchecked.png"
    CheckedImageUrl="/images/checked.png" />

Best Practices

  1. Always provide alt text — Set UncheckedImageAlternateText and CheckedImageAlternateText for accessibility
  2. Use consistent image sizes — Set ImageWidth and ImageHeight to prevent layout shifts
  3. Provide hover statesCheckedImageOverUrl and UncheckedImageOverUrl improve visual feedback
  4. Include disabled states — If your checkbox can be disabled, provide DisabledCheckedImageUrl and DisabledUncheckedImageUrl
  5. Optimize images — Use small, optimized PNG or SVG images for fast loading

Troubleshooting

IssueSolution
Image not appearingVerify CheckedImageUrl and UncheckedImageUrl point to valid image files. Ensure @rendermode InteractiveServer is set.
Standard checkbox still visibleCheck that TargetControlID matches the checkbox's ID exactly.
Hover state not workingVerify CheckedImageOverUrl and UncheckedImageOverUrl paths are correct.
Toggle state not syncingEnsure the target is a checkbox element. Check browser console for JavaScript errors.

See Also