jQuery & JavaScript

Enable or disable an ASP.NET TextBox on a button click with jQuery

jQuery & JavaScript · · Published 2026-11-01

Switching a text box on and off from the browser takes one line of jQuery: .prop("disabled", true). On an ASP.NET page, two details decide whether it behaves: the button must not post the form when you only want a client-side toggle, and you have to know that a disabled field sends nothing back to the server.

The markup

<asp:TextBox ID="txtNotes" runat="server" />
<asp:Button ID="btnToggle" runat="server" Text="Disable" />
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" />
<asp:Label ID="lblStatus" runat="server" />

asp:Button renders <input type="submit">. Without precautions, clicking Disable submits the form, the page reloads from the server and the client-side change is lost.

The script

<script src="https://code.jquery.com/jquery-3.7.1.min.js"
        integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
        crossorigin="anonymous"></script>
<script>
    $(function () {
        var $box = $("#<%= txtNotes.ClientID %>");
        var $btn = $("#<%= btnToggle.ClientID %>");

        $btn.on("click", function (e) {
            e.preventDefault(); // stop the submit button from posting the form

            var disable = !$box.prop("disabled");
            $box.prop("disabled", disable);
            $btn.val(disable ? "Enable" : "Disable");

            if (!disable) {
                $box.trigger("focus");
            }
        });
    });
</script>

e.preventDefault() cancels the button's default action, which for a submit button is sending the form. Returning false from a jQuery handler does the same and also stops propagation. The text of an <input type="submit"> is its value, hence $btn.val(…).

If the button never needs to reach the server, an HTML button is simpler and needs no preventDefault:

<button type="button" id="toggleNotes">Disable</button>

Why prop() and not attr()

disabled is a boolean property of the DOM element. Since jQuery 1.6, .prop() reads and writes such properties, while .attr() works on the HTML attribute. .attr("disabled", false) sets the attribute to the string "false", and because the mere presence of the attribute disables the field, the box stays disabled. .prop("disabled", false) does what it says. To remove an attribute entirely, use .removeAttr("disabled"), but the property call is the documented way to toggle state.

Disabled, read-only and the server

The choice between disabled and readonly is not cosmetic:

StateUser can editReceives focusValue posted
disabledNoNoNo, the field is left out of the submission
readonly (HTML)NoYesYes
Server ReadOnly="true"NoYesSent by the browser but ignored by ASP.NET
Server Enabled="false"NoNoNo; ASP.NET also skips loading post data

When a box is disabled in the browser and the form is posted, ASP.NET receives no value for it. The control is not cleared: it keeps the text it had from view state. So if a user types something, you disable the box, then click Save, the server sees the old text, not the new one. If you want to lock the box but keep its content, use read-only:

$box.prop("readOnly", true).addClass("locked");

Note the capital O: the DOM property is readOnly. jQuery maps "readonly" to it as well, so both spellings work with .prop().

Keeping the state across postbacks

A state set in the browser is lost on the next postback, because the server renders the control again from its own properties. If the toggle must survive a round trip, store it in a hidden field and apply it on the server:

<asp:HiddenField ID="hfNotesDisabled" runat="server" Value="0" />

<script>
    $(function () {
        var $box = $("#<%= txtNotes.ClientID %>");
        var $flag = $("#<%= hfNotesDisabled.ClientID %>");
        $("#<%= btnToggle.ClientID %>").on("click", function (e) {
            e.preventDefault();
            var disable = !$box.prop("disabled");
            $box.prop("disabled", disable);
            $flag.val(disable ? "1" : "0");
            $(this).val(disable ? "Enable" : "Disable");
        });
    });
</script>
protected void Page_Load(object sender, EventArgs e)
{
    bool disabled = hfNotesDisabled.Value == "1";
    txtNotes.Enabled = !disabled;
    btnToggle.Text = disabled ? "Enable" : "Disable";
}

protected void btnSave_Click(object sender, EventArgs e)
{
    lblStatus.Text = txtNotes.Enabled
        ? "Saved: " + HttpUtility.HtmlEncode(txtNotes.Text)
        : "Notes are locked; nothing was changed.";
}

When Enabled is false, ASP.NET renders disabled="disabled" and, since .NET 4, adds the CSS class aspNetDisabled, which you can style. Treat the hidden field as a hint from the client only: if editing must really be forbidden, decide it from server-side data such as the user's role, not from a value the browser can change.

Several boxes at once

Group related fields with a class or a container and toggle them together:

$("#editAddress").on("click", function () {
    var $fields = $(".address input[type=text], .address textarea, .address select");
    var nowDisabled = $fields.first().prop("disabled");
    $fields.prop("disabled", !nowDisabled);
});

A <fieldset disabled> disables every control inside it in one go, which is often the cleanest option: $("#addressSet").prop("disabled", true).

Accessibility

To read or set the text itself, see Get and set a TextBox value with jQuery. To stop double submissions, see Disable the submit button after the form is submitted.

Troubleshooting

Official documentation