Web Form Conundrum: disabled
or readonly
?
Web forms are complex beasts. There are a lot of field types to remember, each with dozens of attributes. It’s hard to know which is the right way to go, especially when presented with a choice between two seemingly similar options for disallowing a field to be edited: disabled
and readonly
.
TL;DR: If you really need it, which you probably don’t, readonly
is what you want.
The Use Case
There are times when you want to expose a bit of data to the user but don’t want them to be able to edit it. For example, your system might not allow a user to edit their username after completing the registration process. In situations like this, you may want to present the username in the context of a profile editing interface without allowing them to edit it.
The best choice in that situation would be to avoid using a form field to display the username, full stop, but if you’re hamstrung and need to drop it in an input
field, you want to make sure the user can’t edit it. That’s when you need to make a choice between disabled
and readonly
.
Both of these attributes are “empty” attributes, meaning they don’t require value assignment:
<label for="username-1">Disabled Username</label>
<input id="username-1" name="username-1" disabled value="AaronGustafson">
<label for="username-2">Readonly Username</label>
<input id="username-2" name="username-2" readonly value="AaronGustafson">
As expected, both also prohibit editing directly in the browser.
The Key Difference
So why do we have two attributes that do the same thing? Unfortunately this is where developers often get confused: the user experience is the same, but the mechanics are quite different.
Fields marked as readonly
are collected along with all of the normal field values in a form submission (“successful controls” in the spec). The only difference between a readonly
field and a regular field is the user experience.
Fields marked as disabled
are ignored when collecting values from the form. In a traditional form submission, the action page would never receive values for a disabled
field, regardless of whether it has a name
attribute. In JavaScript, this is a little trickier as generic DOM access via a form’s elements
collection includes all form controls, including disabled
fields (and buttons, output
elements, etc.). In order to ensure consistency with the spec, it is incumbent upon the JavaScript developer to keep an eye out for disabled
fields so they can throw away their values before processing the form.
Thankfully, most library code I’ve found does this, so it’s not much of an issue if you are working with jQuery’s serialize()
method or even the form-serialize
module for Node (and React, etc.). Confusingly, the Node module enables developers to treat disabled
fields as though they are readonly
. Luckily, that’s not the default behavior.
Don’t Assume
In many of my forms-related talks, I’ve discussed the need for server side validation of info sent from the browser. Even if you have the most robust client-side validation logic in the world, that JavaScript (and your HTML, etc.) is all easily manipulated via common developer tools. If you don’t have equally robust checks running on the server side (be it via an API or simply a form-posting endpoint), you’re opening your system up for abuse.
It’s inconsequential to inspect a form field in the browser, remove the readonly
or disabled
attribute, and submit the form with a change to that field. If you, as the developer, truly don’t want the value of a particular key touched, don’t provide it in a field to begin with. Additionally, don’t accept any values submitted for it. You don’t need to throw an error to the user since it’s an improper use of the system, but you might consider logging it in case you see continued abuse by that user.
I Have Forms to Build, Which Do I Choose?
I want to display data as information, but don’t want a user to update it.
Don’t use a form field at all, display it as text.
I want the data included with the form submission.
Ideally, display the info as text (see above) and mix it into the form submission data on the server side. If that’s not possible, make it a readonly
field an ensure there’s a validation check on the server side.
I do not want the data included in the form submission.
Display the info as text (see above).
Webmentions
Likes
Shares