禁用的表单输入不会显示在请求中

Disabled form inputs do not appear in the request

提问人:hazzik 提问时间:9/9/2011 最后编辑:hazzik 更新时间:3/16/2023 访问量:260320

问:

我在表单中有一些禁用的输入,我想将它们发送到服务器,但 Chrome 将它们从请求中排除。

在不添加隐藏字段的情况下,是否有任何解决方法?

<form action="/Media/Add">
    <input type="hidden" name="Id" value="123" />

    <!-- this does not appear in request -->
    <input type="textbox" name="Percentage" value="100" disabled="disabled" /> 

</form>
HTML 表单 HTTP 浏览器

评论

4赞 hazzik 11/9/2015
@Liam,试图以较低的答案来关闭较少参与的问题,这是非常奇怪的尝试。
0赞 Liam 11/9/2015
一个较老的、较少参加的问题。从技术上讲,这个问题在被问到时应该作为重复关闭。我已经用一个 mod 标记了它,以便进行潜在的合并,可能会也可能不会发生。这取决于他们。
0赞 hazzik 11/9/2015
@Liam事实上,问题各不相同,甚至有些答案看起来很相似。我问如何使“禁用”字段提交值,另一个问题问“原因”
0赞 matcheek 11/1/2016
在我花了几个小时试图解决它之后才到达这里。呃..
0赞 Nicolas Facciolo 4/2/2021
为什么不将 readOnly 属性设置为 true ?

答:

867赞 talha2k 9/9/2011 #1

带有该属性的元素未提交,或者您可以说其值未发布(请参阅HTML 5规范中步骤3下的第二个要点,以构建表单数据集)。disabled

即,

<input type="textbox" name="Percentage" value="100" disabled="disabled" /> 

仅供参考,根据 HTML 4 规范中的 17.12.1

  1. 禁用的控件不会获得焦点。
  2. 在 Tab 键导航中跳过禁用的控件。
  3. 禁用的控件无法成功发布。

您可以在您的案例中使用属性,通过这样做,您将能够发布字段的数据。readonly

即,

<input type="textbox" name="Percentage" value="100" readonly="readonly" />

仅供参考,根据 HTML 4 规范中的 17.12.2

  1. 只读元素接收焦点,但不能由用户修改。
  2. 只读元素包含在 Tab 键导航中。
  3. 只读元素已成功发布。

评论

12赞 Muleskinner 11/21/2014
回答我自己的问题:不,readony 仅适用于 type='text' 和 type='password' 的 <input/> form 控件以及 <textarea/>。readonly 的作用是阻止用户更改控件值。阻止用户更改复选框(或单选类型输入)的值没有多大意义......
5赞 talha2k 5/5/2015
@danielson317 您可以将 select 元素保持“禁用”状态,但也可以添加另一个具有相同值的隐藏输入。
16赞 Nick Bedford 4/4/2019
你有没有发现一些东西并想,“到底是什么让他们认为这是显而易见的?如果我不厌其烦地包含一个可能被禁用或可能不会被禁用的输入字段,这意味着我不希望用户更改它,而不是它应该有效地充当,就好像它从未被声明过一样!
2赞 user1449249 5/9/2020
谢谢你,这很有帮助,无论是答案还是回应。
3赞 voracity 10/12/2020
@NickBedford,尤其是当你认为“哦,我可以通过添加禁用属性来快速安全地处理这个问题。
9赞 Chris Pierce 7/20/2013 #2

如果您绝对必须禁用该字段并传递数据,则可以使用 javascript 将相同的数据输入到隐藏字段中(或者也只是设置隐藏字段)。这将允许您禁用它,但即使您将发布到另一个页面,仍会发布数据。

评论

1赞 Muleskinner 11/20/2014
这个解决方案也是我一直在使用的 - 但正如我刚刚了解到的 - readonly 属性是一个更好的解决方案
25赞 LipeTuga 1/21/2014 #3

使用 Jquery 并使用 ajax 发送数据,您可以解决您的问题:

<script>

$('#form_id').submit(function() {
    $("#input_disabled_id").prop('disabled', false);

    //Rest of code
    })
</script>

评论

1赞 Maduro 9/18/2015
+1 这个解决方案的好处是,当用户超过输入时,您仍然可以使用红色禁用图标 =)
6赞 sricks 6/3/2016
@ArielMaduro你可以用CSS做到这一点cursor:not-allowed;
0赞 Maduro 6/3/2016
@sricks哦,真的吗??你能举个例子吗?
1赞 Andreas 1/7/2017
喜欢这个解决方案而不是使用 ReadOnly,因为禁用的字段无法获得焦点
1赞 Sablefoste 1/25/2022
请注意,如果 Javascript 处于关闭状态,则此解决方案不起作用。最好使用“只读”功能,即原生 HTML。
6赞 Limon 5/29/2014 #4

我正在更新这个答案,因为它非常有用。只需将只读添加到输入即可。

因此,表单将是:

<form action="/Media/Add">
    <input type="hidden" name="Id" value="123" />
    <input type="textbox" name="Percentage" value="100" readonly/>
</form>
-7赞 Amin MyCard 1/7/2016 #5

您可以完全避免禁用,这很痛苦,因为 html 表单格式不会发送任何与标签或其他标签相关的内容。<p>

所以你可以把常规的

<input text tag just before you have `/>

添加这个readonly="readonly"

它不会禁用您的文本,但不会因用户而更改,因此它的工作方式类似于并通过表单发送价值。如果您想让它更像标签,只需删除边框即可<p><p>

13赞 Tom Blodget 3/14/2018 #6

除了启用的输入之外,要发布禁用输入的值,您只需在提交表单时重新启用表单的所有输入即可。

<form onsubmit="this.querySelectorAll('input').forEach(i => i.disabled = false)">
    <!-- Re-enable all input elements on submit so they are all posted, 
         even if currently disabled. -->

    <!-- form content with input elements -->
</form>

如果您更喜欢 jQuery:

<form onsubmit="$(this).find('input').prop('disabled', false)">
    <!-- Re-enable all input elements on submit so they are all posted, 
         even if currently disabled. -->

    <!-- form content with input elements -->
</form>

对于 ASP.NET MVC C# Razor,可以添加提交处理程序,如下所示:

using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post,
    // Re-enable all input elements on submit so they are all posted, even if currently disabled.
    new { onsubmit = "this.querySelectorAll('input').forEach(i => i.disabled = false)" } ))
{
    <!-- form content with input elements -->
}

评论

0赞 cagcak 4/12/2018
jQuery选项上缺少一个引号
3赞 Erik Robinson 9/21/2018 #7

我发现这更容易工作。只读输入字段,然后设置其样式,以便最终用户知道它是只读的。放置在此处的输入(例如来自 AJAX)仍然可以提交,无需额外的代码。

<input readonly style="color: Grey; opacity: 1; ">
4赞 Arth 10/4/2018 #8

从语义上讲,这感觉是正确的行为

我会问自己“为什么我需要提交这个值?"

如果表单上的输入被禁用,则可能不希望用户直接更改值

禁用输入中显示的任何值都应为

  1. 从生成表单的服务器上的值输出,或者
  2. 如果表单是动态的,则可以根据表单上的其他输入进行计算

假设处理表单的服务器与提供表单的服务器相同,则在处理表单时应提供用于重现已禁用输入值的所有信息

事实上,为了保持数据完整性 - 即使禁用的输入的值已发送到处理服务器,您也应该对其进行验证。此验证需要的信息级别与重现值所需的信息级别相同!

我几乎认为只读输入也不应该在请求中发送

很高兴得到纠正,但我能想到的所有需要提交只读/禁用输入的用例实际上都只是变相的样式问题

评论

3赞 jimjim 2/25/2019
不要忘记它的价值可以直接使用 Chrome 开发者工具进行操作
0赞 powderflask 12/11/2022
它总是很容易想象“我能想到的所有用例”==“所有可能的用例”。例如,想象一个动态表单,其中输入仅在特定条件下可编辑,但在其他条件下锁定以进行编辑。此输入的值可能会更改,但随后会在某些情况下被禁用。后端仍然需要更新值,即使输入最终被禁用。
0赞 Arth 12/12/2022
@powderflask我不想想象我已经想到了所有的情况,这就是我做出区分的原因。我想可能有一种游戏机制,你会想在发生某些情况后停止值增加。并仍然将其提交到后端;但是,您仍然需要警惕数据完整性和验证问题,因为此值仍然可以由半称职的用户操作。然而,在大多数情况下,当输入被禁用时,它是因为它依赖于另一个已更改的表单值。因此可以从中推断出
0赞 powderflask 12/14/2022
永远不应该依赖客户端来清理 POST 数据。禁用输入小组件不会阻止中等能力的用户提交该字段的 POST 数据。责任始终在后端。我确实理解一般用例,只是对“我能想到的所有用例”提出异议。HTTP可能出于历史原因(例如,带宽有限,静态内容)以这种方式工作,但这并不能使其在语义上正确。
0赞 Arth 12/14/2022
@powderflask 是的,这正是我的观点,因为无论如何你都必须在后端清理输入——而且很可能从禁用输入的任何条件中推断出来——你可能不需要提交它。不期望/读取禁用的输入将保护您免受恶意用户为其提交错误数据的侵害。好的,如果你有一个特定的用例,需要你提交禁用的输入,那么我建议使用其他答案之一。这个答案更像是“你问的是对的问题吗?
0赞 Pedro Coelho 6/27/2020 #9

除了 Tom Blodget 的回复之外,您还可以简单地添加 @HtmlBeginForm 作为表单操作,如下所示:

 <form id="form" method="post" action="@Html.BeginForm("action", "controller", FormMethod.Post, new { onsubmit = "this.querySelectorAll('input').forEach(i => i.disabled = false)" })"

评论

1赞 Heretic Monkey 6/27/2020
你试过这个代码吗?因为我不明白它是如何工作的。 renders ,这在属性中并不是一件好事。也许您的意思是,它呈现了一个 URL?@Html.BeginForm(...) {...}<form ...> ... </form>@Url.Action("action", "controller")
0赞 Pedro Coelho 6/27/2020
我试过这个代码,异教徒。它在这里起作用了。之前,我使用您提到的 @Url.Action,但并非所有参数。也许“使用”更好,但我不确定
0赞 ABDULRAHMAN ALKHAMEES 8/30/2020 #10

使用 RGBA 值定义颜色

在样式下添加以下代码

<!DOCTYPE html>
<html>
<head>
<style>
#p7 {background-color:rgba(215,215,215,1);}
</style>
</head>
<body>
禁用 灰色 无 传输

<form action="/Media/Add">
    <input type="hidden" name="Id" value="123" />

    <!-- this does not appear in request -->
    <input id="p7" type="textbox" name="Percentage" value="100" readonly="readonly"" /> 

</form>

结果

2赞 Lwin Htoo Ko 11/3/2020 #11

简单的解决方法 - 只需使用隐藏字段作为选择、复选框和单选的占位符。

从此代码到 -

<form action="/Media/Add">
    <input type="hidden" name="Id" value="123" />

    <!-- this does not appear in request -->
    <input type="textbox" name="Percentage" value="100" disabled="disabled" /> 
    <select name="gender" disabled="disabled">
          <option value="male">Male</option>
          <option value="female" selected>Female</option>
    </select>

</form>

该代码 -

<form action="/Media/Add">
    <input type="hidden" name="Id" value="123" />

    <input type="textbox" value="100" readonly /> 

    <input type="hidden" name="gender" value="female" />
    <select name="gender" disabled="disabled">
          <option value="male">Male</option>
          <option value="female" selected>Female</option>
    </select>
</form>
1赞 Lundy Bin Abraham 9/16/2022 #12

<input type="textbox" name="" value="100" disabled/>

<input type="textbox" name="" value="100" readonly/>

如果您使用的是像 PHP Laravel 这样的框架,则没有 name 属性的元素将读取为 unset

<input type="textbox" value="100" disabled/>
0赞 Mr.B 11/10/2022 #13

我遇到了完全相同的问题,但对我不起作用,因为我选择了 HTML 元素,并且它是只读状态,允许更改其值。 所以我在一个条件中使用了 select,在另一个条件中使用了 input:

   <% If IsEditWizard Then   %>
                            <%For Each item In GetCompaniesByCompanyType("ResponsibleEntity")%>
                            <% If item.CompanyCode.EqualsIgnoreCase(prCompany.GetAsString("LinkedCompany")) Then   %>
                            <input type="text" value="<%: item.CompanyName  %>" tabindex="3" size="12" maxlength="12" readonly="readonly" />
                            <input type="hidden" id="LinkedCompany" name="LinkedCompany" value="<%:item.CompanyCode %>" tabindex="3" size="12" maxlength="12" />
                            <%End If %>
                            <%Next %>
                            <%Else %>
                            <select id="LinkedCompany" name="LinkedCompany" class="w-auto" <%= If(IsEditWizard, "disabled", "") %>>
                                <option value="">Please Select</option>
                                <%For Each item In GetCompaniesByCompanyType("ResponsibleEntity")%>
                                <option value="<%:item.CompanyCode %>" <%: IIf(item.CompanyCode.EqualsIgnoreCase(prCompany.GetAsString("LinkedCompany")), "selected", String.Empty) %>><%: item.CompanyName %></option>
                                <%Next %>
                            </select>

                            <%End If %>