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

Posted

技术标签:

【中文标题】如何使整个 HTML 表单“只读”?【英文标题】:How can I make an entire HTML form "readonly"? 【发布时间】:2011-03-31 07:03:14 【问题描述】:

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

据我所知,一些表单控件可以是readonly,而所有表单控件都可以是disabled,不同之处在于您仍然可以tab 到只读字段。

有没有办法将整个表单标记为只读/禁用/静态,而不是逐个字段地执行此操作,以便用户无法更改任何控件?

【问题讨论】:

【参考方案1】:

将输入字段和其他内容包装到<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>

【讨论】:

对我来说简单而伟大的解决方案。谢谢 客户端的最佳解决方案 :) +1 很简单,这是迄今为止最好的客户端解决方案。 注意:这样做的副作用是“作为 [字段集] 后代的表单控件,除了其第一个可选 元素的后代...... [不] 接收任何浏览事件,比如鼠标点击或焦点相关的点击”(developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)。因此,您可能在后代上定义的任何 js 事件侦听器都可能不起作用。 @EricFreese 仅在禁用状态下,这在 99 % 的情况下都是您想要的。【参考方案2】:

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

复选框 收音机盒 文件上传 ...更多..

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

另一个解决方案,在下面的演示中展示,是在form 元素的顶部放置一个层,这将阻止与form 元素内的所有元素的任何交互,因为该层设置有更大的z-index 值:

演示:

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>

【讨论】:

请注意,CSS 解决方案不完整,因为它不会阻止键盘导航。【参考方案3】:

您可以使用此功能禁用表单:

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

See the working demo here

请注意,它使用 jQuery。

【讨论】:

+1 谢谢,但我不能使用客户端解决方案,请参阅更新的问题(对不起,我的错)【参考方案4】:

在确认页面,不要把内容放在可编辑的控件中,直接写到页面上就行了。

【讨论】:

这确实是最明智的方法。不要向用户展示不可编辑的表单,否则您最终会成为“Least Astonishment”问题中的一个条目。 怎么样?如何显示复选框及其选中/未选中条件,或带有所选项目的单选组等? @Mawg 也许只列出“选定”项目而不使用复选框是一个选项。就像在披萨订单确认中一样:只需列出您选择的所有成分。 在这种情况下不是,但感谢您提供的一个很好的横向思考,它可能会帮助其他人。【参考方案5】:

这是禁用指定元素中所有输入文本区域选择按钮的理想解决方案.

对于 jQuery 1.6 及以上版本

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

或者

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

jQuery 1.5 及以下

$('#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;)【参考方案6】:

据我所知,没有内置方法可以执行此操作,因此您需要根据表单的复杂程度提出自定义解决方案。你应该阅读这篇文章:

Convert HTML forms to read-only(更新帖子链接损坏,archived link

编辑:根据您的更新,您为什么如此担心它是只读的?您可以通过客户端执行此操作,但如果不是,则必须将所需的标签添加到每个控件或转换数据并将其显示为没有控件的原始文本。如果您试图将其设置为只读以便下一篇文章不会被修改,那么您就会遇到问题,因为任何人都可以将帖子弄乱以产生他们想要的任何东西,所以当您实际上最终收到数据时,您最好检查它再次确保它是有效的。

【讨论】:

+1 谢谢,但我不能使用客户端解决方案,请参阅更新的问题(对不起,我的错) “根据你的更新,你为什么这么担心让它只读?你可以通过客户端来做”对不起,但是 1)我不能在客户端做(不是我的选择)和 2)如果用户觉得他正在改变可能让他感到困惑的事情。 @mawg 好吧,如果它纯粹是为了视觉效果,那么我唯一可以推荐的是将所有内联控件替换为其等效文本或将 readonly 属性添加到控件中。没有灵丹妙药,我感觉这就是您正在寻找的东西。您可以发布允许修改的代码的 sn-p 吗?为您正在使用的内容打下基础会有所帮助。 +1 感谢您的建议。我以前从来没有真正注意到,但如果表格和模糊记得它们的只读版本,我一定填写了 100 或 1,000 个,而不仅仅是文本。也许我应该再填写一些并观察:-) 惊喜... 6 年后链接失效了。【参考方案7】:

没有完全兼容的官方 HTML 方法可以做到这一点,但一点 javascript 可以大有帮助。 您会遇到的另一个问题是禁用的字段不会显示在 POST 数据中

【讨论】:

如果您已经验证了数据,则无论如何都需要将其保存在服务器端。将它来回发送给客户端是一个很大的安全漏洞。即使您使用 css、js 或 html 来冻结字段,您也可以使用 firebug 或手动更改下一个 HTTP 请求来编辑它们 +1 谢谢,但我不能使用客户端解决方案,请参阅更新的问题(对不起,我的错)【参考方案8】:

所有浏览器都支持的另一种简单方法是:

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;

但请注意,这种方法仍然可以使用制表符,并且用户仍然可以操作具有焦点的元素。

【讨论】:

我不建议这样做,它只会改变表单的视觉外观,并且(正如您还指出的)您仍然可以更改字段值,甚至仅通过键盘导航提交表单。从可访问性的角度来看,它也不是很好。使用屏幕阅读器的人不会将此表单视为已禁用,因为它在语义上并未禁用。 我最喜欢这个。它没有任何挑剔的地方。如果您使用禁用 - 您有可能无法保存表单字段数据。如果您使用只读 - 它也是错误的并且不能与下拉列表一起正常工作。而且这种方法也适用于更优雅和简洁的'form'和'fieldset' - 使完整的表单不可更改。同样 - 使用 CSS,您可以选择以最适合您的界面设计、样式和视觉提示的方式显示现在不可用的部分。【参考方案9】:

为所有的表单 id 编号并在 JS 中运行一个 for 循环。

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

【讨论】:

+1 谢谢,但我不能使用客户端解决方案,请参阅更新的问题(对不起,我的错)【参考方案10】:

一个简单的需求:以最少的代码和令人头疼的方式显示不可编辑的表单(以后可以编辑)。

如果您不能使用“禁用”属性(因为它会删除 POST 时的值输入),并注意到 html 属性“只读”仅适用于 textarea 和一些输入(文本、密码、搜索,到目前为止,我'已经看到),最后,如果您不想费心复制所有带有隐藏输入逻辑的选择、复选框和单选框, 您可能会发现以下功能或任何您喜欢的内部逻辑:

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');
    
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

没有什么比删除这些只读文件更容易的了

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','');
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案11】:

最简单的方法

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

【讨论】:

确实如此,但这只是一个例子,您可以将第二个选择器更改为任何其他选择器,例如 $('#yourform .yourclass_for_inputs').prop('readonly', true);跨度> 不适用于选择字段【参考方案12】:

我宁愿使用 jQuery:

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

find() 会比 children() 更深入到第 n 个嵌套子级,而 children() 只查找直系子级。

【讨论】:

谢谢,我会支持你的尝试,因为你是新人。但是,请注意,我明确要求仅提供服务器端解决方案。那时我只写过 php,还没有写过 JS。一个友好的提示来阅读这个问题,因为有些人实际上可能会为此反对你:-(欢迎加入:-)【参考方案13】:

您在表单上添加 html 不可见层。比如

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

和风格:

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

当然用户可以在网络浏览器中隐藏这一层。

【讨论】:

以上是关于如何使整个 HTML 表单“只读”?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access 表单只读

如何使用角度指令动态地使表单元素只读?

如何使用 jQuery 提交带有部分只读输入的表单?

使某个用户类型的表单只读

如何使复选框只读?没有禁用?

如何使登录表单在 Django 的整个站点上可用