How can I make an entire HTML form "readonly"?
Asked Answered
N

16

240

I have two pages with HTML forms. The first page has a submission form, and the second page has an acknowledgement form. The first form offers a choice of many controls, while the second page displays the data from the submission form again with a confirmation message. On this second form all fields must be static.

From what I can see, some form controls can be readonly and all can be disabled, the difference being that you can still tab to a readonly field.

Rather than doing this field by field is there any way to mark the whole form as readonly/disabled/static such that the user can't alter any of the controls?

Ningsia answered 18/8, 2010 at 0:8 Comment(0)
C
477

Wrap the input fields and other stuff into a <fieldset> and give it the disabled="disabled" attribute.

Example (http://jsfiddle.net/7qGHN/):

<form>
    <fieldset disabled="disabled">
        <input type="text" name="something" placeholder="enter some text" />
        <select>
            <option value="0" disabled="disabled" selected="selected">select somethihng</option>
            <option value="1">woot</option>
            <option value="2">is</option>
            <option value="3">this</option>
        </select>
    </fieldset>
</form>
Conductivity answered 19/6, 2013 at 8:24 Comment(10)
Note: This has the side effect of making "the form controls that are [the fieldsets] descendants, except descendants of its first optional <legend> element ... [not] receive any browsing events, like mouse clicks or focus-related ones" (developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset). So any js event listeners you may have defined on descendants may not function.Coachman
@EricFreese Only in disabled state, which is what you want in 99 % of cases.Streamlet
This works but Values for disabled form elements are not passed to the processor method.Argot
@HarishKarthick which is exactly what you want.Conductivity
Are you kidding me? I've been coding if/else statements for all these years. I finally decide to see if there's a better way and, and not only is there a better way, it's incredibly easy. The only thing this doesn't do is change the class on each input to visually indicate it is read only.Zerlina
To also indicate to the user that the inputs are disabled, put the following jquery at the bottom of your page: if($('#fieldsetid').prop('disabled')){ $('#fieldsetid :input').addClass('readonly'); }Zerlina
Note, this doesn't send data when form is submitted, not really a readonly mode per sayWroth
If I want to disable conditionally, is there anyway to pass something into disabled like false that actually keeps it enabled? Using angular, I was able to do this <fieldset disabled="disabled", data-ng-disabled="false"> - feels awkwardSledge
not the correct answer. this doesn't make the form readonly, but disabledIatrics
WRNING: Upon saving a form that has been disabled - when now saving - all of the field values will be saved as "" in the database. In other words... DELETED!Gibbon
R
23

Edit (Jan 5, 24):

👉 Use the inert attribute on the whole <form> container element

The inert attribute can be added to sections of content that should not be interactive. When an element is inert, it along with all of the element's descendants, including normally interactive elements such as links, buttons, and form controls are disabled because they cannot receive focus or be clicked.

Please ignore the below (unrecommended) method


Old answer:

Not all form elements can be set to readonly, for example:
  • checkboxes
  • radio boxes
  • file upload
  • ...more..

Then the reasonable solution would be to set all form elements' disabled attributes to true, since the OP did not state that the specific "locked" form should be sent to the server (which the disabled attribute does not allow).

Another solution, which is presented in the demo below, is to place a layer on top of the form element which will prevent any interaction with all the elements inside the form element, since that layer is set with a greater z-index value:

DEMO:

var form = document.forms[0], // form element to be "readonly"
    btn1 = document.querySelectorAll('button')[0],
    btn2 = document.querySelectorAll('button')[1]

btn1.addEventListener('click', lockForm)
btn2.addEventListener('click', lockFormByCSS)

function lockForm(){
  btn1.classList.toggle('on');
  [].slice.call( form.elements ).forEach(function(item){
      item.disabled = !item.disabled;
  });
}

function lockFormByCSS(){
  btn2.classList.toggle('on');
  form.classList.toggle('lock');
}
form{ position:relative; } 
form.lock::before{
  content:'';
  position:absolute;
  z-index:999;
  top:0;
  right:0;
  bottom:0;
  left:0;
}

button.on{ color:red; }
<button type='button'>Lock / Unlock Form</button>
<button type='button'>Lock / Unlock Form (with CSS)</button>
<br><br>
<form>
  <fieldset>
    <legend>Some Form</legend>
    <input placeholder='text input'>
    <br><br>
    <input type='file'>
    <br><br>
    <textarea placeholder='textarea'></textarea>
    <br><br>
    <label><input type='checkbox'>Checkbox</label>
    <br><br>
    <label><input type='radio' name='r'>option 1</label>
    <label><input type='radio' name='r' checked>option 2</label>
    <label><input type='radio' name='r'>option 3</label>
    <br><br>
    <select>
      <option>options 1</option>
      <option>options 2</option>
      <option selected>options 3</option>
    </select>
  </fieldset>
</form>
Reichenberg answered 24/3, 2014 at 11:45 Comment(2)
Please note that the CSS solution is incomplete as it does not prevent keyboard navigation.Philosopher
You may actually be able to disable keyboard navigation by messing with evt.preventDefault() or possibly tabindex but it's still a clumsy solution that will mess with accessibilityMagnetochemistry
S
14
<form inert>

This won't change the styling of the form but will stop all the inputs from being focusable and stop any buttons from being clickable.

Slunk answered 26/8, 2022 at 11:30 Comment(4)
This is a new one to me. Thanks. They just keep updating HTML. Looks like most major browsers support itNingsia
This will make the form completely unaccessible and undetectable for assistive technologies.Further
Yes good point. Depends on the scenario, but in most cases it’s better for a screen reader to tell the user there is a disabled button than to tell them nothing.Slunk
Not supported by Firefox :(Portentous
F
7

You can use this function to disable the form:

function disableForm(formID){
  $('#' + formID).children(':input').attr('disabled', 'disabled');
}

See the working demo here

Note that it uses jQuery.

Fleshpots answered 18/8, 2010 at 0:30 Comment(1)
+1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad)Ningsia
S
6

On the confirmation page, don't put the content in editable controls, just write them to the page.

Salzburg answered 18/8, 2010 at 3:44 Comment(4)
This really is the sanest approach. Don't present an uneditable form to a user, or you'll end up being an entry in the "Least Astonishment" question.Preachment
how? How can I display a checkbox and its check/not-checked condition, or a radio group with its selected item, etc?Ningsia
@Ningsia maybe it would be an option to just list the 'selected' items, without checkboxes. Like on a pizza order confirmation: just list all the ingredients you selected.Reiche
In this case not, but thanks for a good piece of lateral thinking which might help others.Ningsia
P
6

This is an ideal solution for disabling all inputs, textareas, selects and buttons in a specified element.

For jQuery 1.6 and above:

// To fully disable elements
$('#myForm :input').prop('disabled', true); 

Or

// To make elements readonly
$('#myForm :input').prop('readonly', true); 

jQuery 1.5 and below:

$('#myForm :input').prop('disabled', 'disabled');

And

$('#myForm :input').prop('readonly', 'readonly');
Pelt answered 11/9, 2018 at 22:32 Comment(1)
also $('#myForm').on('focus',function(e){$(e.targetElement).blur();}).submit(function(e){e.preventDefault();return false;})Tananarive
P
5

There is no built-in way that I know of to do this so you will need to come up with a custom solution depending on how complicated your form is. You should read this post:

Convert HTML forms to read-only (Update: broken post link, archived link)

EDIT: Based on your update, why are you so worried about having it read-only? You can do it via client-side but if not you will have to add the required tag to each control or convert the data and display it as raw text with no controls. If you are trying to make it read-only so that the next post will be unmodified then you have a problem because anyone can mess with the post to produce whatever they want so when you do in fact finally receive the data you better be checking it again to make sure it is valid.

Portis answered 18/8, 2010 at 0:20 Comment(6)
+1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad)Ningsia
"Based on your update, why are you so worried about having it read only? You can do it via client-side" Sorry, but 1) I can't do it client side (not my choice) and 2) if it looks to the user like he is changing things that might confuse him.Ningsia
@mawg well if it is purely for visuals then, the only thing I can recommend is replace all the controls inline with their text equivalent or adding the readonly property to the controls. There is no silver bullet and I get a sense that is what you are looking for. Can you post a snippet of the code that you are allowed to modify? It would help to just get a basis for what you are working with.Portis
+1 thanks for the suggestion. I never really noticed before, but I must have filled in 100s or 1,000s if forms & vaguely remember a readonly version of them, not just text. Maybe I should fill in a few more & observe :-)Ningsia
This is not a solution to the much visited question, techouse provided the correct solution.Forkey
Surprise... 6 years later the link is not working anymore.Assimilate
K
4

There's no fully compliant, official HTML way to do it, but a little javascript can go a long way. Another problem you'll run into is that disabled fields don't show up in the POST data

Klump answered 18/8, 2010 at 0:16 Comment(2)
If you've already validated the data you need to save it server side anyway. Sending it back and forth to the client is a big ol' security hole. Even if you use css, js or html to freeze the fields you can edit 'm with firebug or by manually changing the next HTTP requestKlump
+1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad)Ningsia
P
1

Have all the form id's numbered and run a for loop in JS.

 for(id = 0; id<NUM_ELEMENTS; id++)
   document.getElementById(id).disabled = false; 
Pteryla answered 18/8, 2010 at 0:44 Comment(1)
+1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad)Ningsia
M
1

Easiest way

$('#yourform .YOUR_CLASS_FOR_INPUTS').prop('readonly', true);
Mccormac answered 11/9, 2018 at 14:6 Comment(3)
it is true, but this is just ax example you can change your second selector to any other for example $('#yourform .yourclass_for_inputs').prop('readonly', true);Mccormac
Does not work on select fieldsGibbon
The better approach would be $('#yourform :input')....Englishry
T
1

A simple need : display non-editable form (that can become editable later on) with minimum code and headache.

If you can't use the 'disabled' attribut (as it erases the value's input at POST), and noticed that html attribut 'readonly' works only on textarea and some input(text, password, search, as far I've seen), and finally, if you don't want to bother with duplicating all your select, checkbox and radio with hidden input logics, you might find the following function or any of his inner logics to your liking :

addReadOnlyToFormElements = function (idElement) {
    
        // textarea an input of type (text password search) work with the html readonly
        $('#' + idElement + ' textarea, #' + idElement + ' input').prop('readonly',true);
    
        // but you still have to destroy their associated objects, as I.E, datepicker (in our old project, datepicker is appended to input where 'Date' is in name attribut, don't ask why)
        $('#' + idElement + ' input[name*="Date"]').datepicker('destroy');
    
        // html readonly don't work on input of type checkbox and radio, neither on select. So, a safe trick is to disable the non-selected items
        $('#' + idElement + ' input[type="checkbox"]:not(:checked), #' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',true); 
        $('#' + idElement + ' select>option:not([selected])').prop('disabled',true);
    
        // and, on the selected ones, to disable mouse/keyoard events and mimic readOnly appearance
        $('#' + idElement + ' input[type="checkbox"]:checked').prop('tabindex','-1').css('pointer-events','none').css('opacity','0.5');
        $('#' + idElement + ' input[type="radio"]:checked').css('opacity','0.5');
        $('#' + idElement + ' select').css('background-color','#eee');
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

And there's nothing easier than to remove these readonly

removeReadOnlyFromFormElements = function (idElement) {

    // just remove the html readonly on textarea and input
    $('#' + idElement + ' textarea, #' + idElement + ' input').prop('readonly',false);

    // and restore their Objects, as I.E, datepicker
    $('#' + idElement + ' input[name*="Date"]').datepicker();

    // Remove the disabled attribut on non-selected
    $('#' + idElement + ' input[type="checkbox"]:not(:checked), #' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',false); 
    $('#' + idElement + ' select>option:not([selected])').prop('disabled',false);

    // Restore mouse/keyboard events and remove readOnly appearance on selected ones
    $('#' + idElement + ' input[type="checkbox"]:checked').prop('tabindex','').css('pointer-events','').css('opacity','');
    $('#' + idElement + ' input[type="radio"]:checked').css('opacity','');
    $('#' + idElement + ' select').css('background-color','');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Thurlow answered 11/2, 2022 at 20:14 Comment(0)
D
0

I'd rather use jQuery:

$('#'+formID).find(':input').attr('disabled', 'disabled');

find() would go much deeper till nth nested child than children(), which looks for immediate children only.

Directoire answered 25/9, 2015 at 13:26 Comment(1)
Thanks, I will upvote you for trying, since you are new. BUT, please note that I clearly asked for a server side only solution. At that time I only coded PHP and not yet JS. A friendly hint to read the question as some might actually downvote you for this :-( Welcome aboard :-)Ningsia
K
0

Another simple way that's supported by all browsers would be:

HTML:

<form class="disabled">
  <input type="text" name="name" />
  <input type="radio" name="gender" value="male">
  <input type="radio" name="gender" value="female">
  <input type="checkbox" name="vegetarian">
</form>

CSS:

.disabled {
  pointer-events: none;
  opacity: .4;
}

But be aware, that the tabbing still works with this approach and the elements with focus can still be manipulated by the user.

Kisangani answered 13/5, 2020 at 10:4 Comment(2)
I wouldn't recommend this, it's only changing the visual appearance of the form and (as you also pointed out) you are still able to change field values and even submit the form only by keyboard navigation. From the accessibility perspective it's also not very good. People with screen readers won't see this form as disabled as it's semantically not disabled.Stearn
I like this best. It does not have anything finicky about it. If you use disable - you stand chance of having the form fields data not being saved. If you use readonly - it is also buggy and does not work properly with drop lists. And this method also works on both 'form' and 'fieldset' which is more elegant and concise - rendering the complete form unchangeable. As well - with the CSS you have the choice to display the now unusable sections in the way that suits your interface design and style and visual cues best.Gibbon
P
0

You can use an opaque layer over the form:

  1. Put position: relative on the form
  2. Add the transparent blocking div as a child of this form with position: absolute and top, bottom, left, right equal to 0
Privation answered 12/8, 2022 at 12:46 Comment(0)
S
-1

You add html invisible layer over the form. For instance

<div class="coverContainer">
<form></form>
</div>

and style:

.coverContainer{
    width: 100%;
    height: 100%;
    z-index: 100;
    background: rgba(0,0,0,0);
    position: absolute;
}

Ofcourse user can hide this layer in web browser.

Stevens answered 7/6, 2019 at 8:44 Comment(0)
P
-2

To make a whole fieldset disabled conditionally in angular you can do like this:

 <fieldset [attr.disabled]="isEditable ? null : 'disabled'">
Perspective answered 29/3, 2022 at 10:38 Comment(2)
no one is asking anything about 'angular'Gibbon
to be fair, if you understand html and js frameworks, you clearly see that they meant <fieldset disabled>. which is not incorrect.Gullible

© 2022 - 2024 — McMap. All rights reserved.