如何使整个HTML表单“只读”?

232

我有两个带有HTML表单的页面。第一页有一个提交表单,第二页有一个确认表单。第一个表单提供了许多控件的选择,而第二个页面将提交表单的数据再次显示,并显示确认消息。在这个第二个表单中,所有字段都必须是静态的。

从我所看到的,一些表单控件可以是只读(readonly),所有控件都可以是禁用(disabled),不同之处在于您仍然可以使用tab键来访问只读字段。

是否有任何方法可以将整个表单标记为只读(readonly)/禁用(disabled)/静态,以便用户无法更改任何控件,而不是逐个字段进行此操作?

16个回答

464

将输入字段和其他内容包装在<fieldset>中,并为其添加disabled="disabled"属性。

示例(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>


2
注意:这会产生“表单控件,它们是[fieldset]的后代,除了第一个可选的<legend>元素的后代之外...将不会接收任何浏览事件,如鼠标点击或与焦点相关的事件”(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)。因此,您可能定义在后代上的任何js事件侦听器可能无法正常工作。 - Eric Freese
5
仅在禁用状态下才能实现,这正是99%情况下你所需要的。 - Jan Kalfus
3
这个可以工作但是禁用表单元素的值不会传递到处理器方法中。 - Harish Karthick
4
注意,这并不是在表单提交时发送数据,也不完全是只读模式。 - Herz3h
2
这并不会使表单只读,而是禁用了它。 - Teo Mihaila
显示剩余5条评论

14

并非所有的表单元素都可以设置为readonly,例如:

  • 复选框
  • 单选框
  • 文件上传
  • ...更多...

因此,合理的解决方案是将所有表单元素的disabled属性设置为true,因为OP没有说明特定的“锁定”表单应该被发送到服务器(disabled属性不允许这样做)。

另一种解决方案是,在form元素上放置一个图层,以防止与form元素内所有元素的任何交互,因为该图层设有更大的z-index值:

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>


4
请注意,CSS的解决方案并不完整,因为它无法防止键盘导航。 - Tanriol

11
<form inert>

这不会改变表单的样式,但会使所有输入框无法聚焦并停止任何按钮的可点击性。


2
这对我来说是新鲜事。谢谢。HTML不断更新。看起来大多数主流浏览器都支持它。(https://caniuse.com/?search=inert) - Mawg says reinstate Monica
1
这将使得表单对辅助技术完全无法访问和检测。 - Quentin Albert
是的,说得好。这取决于情况,但在大多数情况下,让屏幕阅读器告诉用户有一个禁用的按钮比什么都不告诉他们要好。 - Ollie Williams
不支持Firefox :( - Jerther

8
您可以使用此函数来禁用表单:
function disableForm(formID){
  $('#' + formID).children(':input').attr('disabled', 'disabled');
}

点击此处查看演示

请注意,它使用jQuery。


+1 谢谢,但我不能使用客户端解决方案,请参见更新的问题(抱歉,我的错) - Mawg says reinstate Monica

6

这是一个理想的解决方案,可以禁用指定元素中的所有 输入框文本域选择框按钮

对于 jQuery 1.6 及以上版本:

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

或者

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

jQuery 1.5 and below:

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

并且
$('#myForm :input').prop('readonly', 'readonly');

同时,$('#myForm').on('focus',function(e){$(e.targetElement).blur();}).submit(function(e){e.preventDefault();return false;}) - Wil

6
在确认页面上,不要将内容放在可编辑的控件中,而是直接写入页面。

1
这确实是最明智的方法。不要向用户呈现不可编辑的表单,否则你最终会成为“最令人惊讶”的问题之一。 - kibibu
1
如何在界面上显示复选框及其选中/未选中状态,或单选按钮组和其选定项等? - Mawg says reinstate Monica
1
@Mawg 或许可以考虑只列出“已选择”的项目,而无需复选框。就像在披萨订单确认页面一样:只列出您所选的所有配料。 - marc82ch
在这种情况下不需要,但感谢您提供了一个好的横向思考的方法,可能会帮助其他人。 - Mawg says reinstate Monica

5
我不知道有内置的方法可以做到这一点,因此您需要根据表单的复杂程度想出一种自定义解决方案。您应该阅读这篇文章:将HTML表单转换为只读更新链接已失效,存档链接编辑: 根据您的更新,为什么您如此担心它是只读的?您可以通过客户端来实现,但如果不行,则必须向每个控件添加所需的标记或将数据转换并将其显示为无控件的原始文本。如果您试图使其只读,以便下一篇帖子不被修改,则会产生问题,因为任何人都可以瞎搞以产生他们想要的结果,因此当您最终确实收到数据时,最好再次检查以确保其有效。

+1 谢谢,但我不能使用客户端解决方案,请参见更新的问题(抱歉,我的错) - Mawg says reinstate Monica
根据你的更新,为什么你这么担心它是只读的?你可以通过客户端来实现它。很抱歉,但是1)我无法在客户端执行此操作(不是我的选择);2) 如果用户看起来像他正在更改事物,那可能会让他感到困惑。 - Mawg says reinstate Monica
@mawg 如果这纯粹是为了视觉效果,那么我唯一能建议的就是将所有控件替换为它们的文本等效项或在控件上添加readonly属性。没有万能解决方案,我感觉这就是你在寻找的。你可以发布一段你被允许修改的代码片段吗?这将有助于让我们了解你正在处理什么。 - Kelsey
谢谢您的建议。我以前从未注意到,但我一定填写了数百或数千个表格,并模糊地记得它们有只读版本,而不仅仅是文本。也许我应该再填写几个并观察一下 :-) - Mawg says reinstate Monica
这不是一个解决经常被提出的问题的方案,techouse提供了正确的解决方案。 - Oded Niv
3
惊讶的是,6年后这个链接已经失效了。 - mwallisch

4

虽然没有完全符合官方HTML标准的方法,但是一点点JavaScript可以很好地解决问题。另一个问题是禁用的字段不会出现在POST数据中。


4
如果您已经验证了需要保存的数据,无论如何都需要将其保存在服务器端。来回发送数据到客户端是一个巨大的安全漏洞。即使您使用css、js或html来冻结字段,您仍然可以通过使用firebug或手动更改下一个HTTP请求来编辑它们。 - Michael Clerx
+1 谢谢,但我不能使用客户端解决方案,请参见更新的问题(抱歉,我的错) - Mawg says reinstate Monica

1

最简单的方法

$('#yourform .YOUR_CLASS_FOR_INPUTS').prop('readonly', true);

这是真的,但这只是一个例子,你可以将第二个选择器更改为任何其他选择器,例如:$('#yourform .yourclass_for_inputs').prop('readonly', true); - Samir Rahimy
仅限部分字段无法正常工作。 - TV-C-1-5
更好的方法是 $('#yourform :input').... - jlh

1

将所有表单ID编号,并在JS中运行for循环。

 for(id = 0; id<NUM_ELEMENTS; id++)
   document.getElementById(id).disabled = false; 

+1 谢谢,但我不能使用客户端解决方案,请参见更新的问题(抱歉,我的错) - Mawg says reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接