226

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?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551

16 Answers16

461

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>
Pang
  • 9,564
  • 146
  • 81
  • 122
Klemen Tusar
  • 9,261
  • 4
  • 31
  • 28
  • 1
    Note: This has the side effect of making "the form controls that are [the fieldsets] descendants, except descendants of its first optional element ... [not] receive any browsing events, like mouse clicks or focus-related ones" (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset). So any js event listeners you may have defined on descendants may not function. – Eric Freese Sep 20 '16 at 18:18
  • 5
    @EricFreese Only in disabled state, which is what you want in 99 % of cases. – Jan Kalfus May 11 '18 at 12:51
  • 2
    This works but Values for disabled form elements are not passed to the processor method. – Harish Karthick Sep 23 '19 at 03:00
  • @HarishKarthick which is exactly what you want. – Klemen Tusar Apr 06 '20 at 11:31
  • 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. – Vincent Apr 08 '20 at 22:08
  • 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'); } – Vincent Apr 08 '20 at 22:34
  • 3
    Note, this doesn't send data when form is submitted, not really a readonly mode per say – Herz3h Nov 20 '20 at 11:34
  • 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 `
    ` - feels awkward
    – Adam Hughes Jan 13 '21 at 17:59
  • 2
    not the correct answer. this doesn't make the form readonly, but disabled – Teo Mihaila Oct 11 '21 at 17:10
  • 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! – TV-C-1-5 Feb 24 '22 at 03:20
13

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>
vsync
  • 118,978
  • 58
  • 307
  • 400
8

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.

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
8
<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.

Ollie Williams
  • 1,996
  • 3
  • 25
  • 41
6

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

Doobi
  • 4,844
  • 1
  • 22
  • 17
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.

quantme
  • 3,609
  • 4
  • 34
  • 49
Kelsey
  • 47,246
  • 16
  • 124
  • 162
  • +1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad) – Mawg says reinstate Monica Aug 18 '10 at 03:02
  • "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. – Mawg says reinstate Monica Aug 18 '10 at 03:45
  • @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. – Kelsey Aug 18 '10 at 04:50
  • +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 :-) – Mawg says reinstate Monica Aug 18 '10 at 06:26
  • This is not a solution to the much visited question, techouse provided the correct solution. – Oded Niv Jan 15 '16 at 07:09
  • 3
    Surprise... 6 years later the link is not working anymore. – mwallisch Sep 14 '16 at 14:26
5

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');
Mystical
  • 2,505
  • 2
  • 24
  • 43
  • also $('#myForm').on('focus',function(e){$(e.targetElement).blur();}).submit(function(e){e.preventDefault();return false;}) – Wil Oct 18 '21 at 08:27
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

Michael Clerx
  • 2,928
  • 2
  • 33
  • 47
  • 4
    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 request – Michael Clerx Aug 18 '10 at 01:04
  • +1 Thanks, but I can't use client side side solutions, see updated question (sorry, my bad) – Mawg says reinstate Monica Aug 18 '10 at 03:01
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; 
T.T.T.
  • 33,367
  • 47
  • 130
  • 168
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>
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.

Pang
  • 9,564
  • 146
  • 81
  • 122
user163861
  • 375
  • 2
  • 10
  • 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 :-) – Mawg says reinstate Monica Sep 25 '15 at 13:53
0

Easiest way

$('#yourform .YOUR_CLASS_FOR_INPUTS').prop('readonly', true);
Samir Rahimy
  • 2,580
  • 1
  • 18
  • 10
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.

  • 1
    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. – acme Mar 08 '21 at 14:10
  • 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. – TV-C-1-5 Feb 24 '22 at 03:47
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
Nicolas Bodin
  • 1,431
  • 1
  • 20
  • 25
-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.

Marcin Żurek
  • 145
  • 1
  • 3
-2

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

 <fieldset [attr.disabled]="isEditable ? null : 'disabled'">