在表单中按 Enter 时执行的默认操作

Posted

技术标签:

【中文标题】在表单中按 Enter 时执行的默认操作【英文标题】:Default action to execute when pressing enter in a form 【发布时间】:2011-07-26 01:04:08 【问题描述】:

我有一个带有两个按钮和几个输入字段的 jsf 1.2 表单。第一个按钮丢弃输入的值并使用数据库中的值重新填充页面,第二个按钮保存输入的值。当用户在光标位于其中一个输入字段时按下回车键时,会出现此问题,提交表单并执行与第一个按钮关联的操作。

代码如下所示:

<h:commandButton action="#bean.reset" value="Reset" />
<h:commandButton action="#bean.save" value="Save" />

<!-- h:datatable with several h:inputText elements -->

是否可以在按下回车时将特定按钮声明为默认操作?这种行为实际上是在某处指定的吗?

【问题讨论】:

Trinidad 在它的表单标签中提供了这样的功能。 link 嗨,Jörn,我会为只有一个输入字段的表单禁用自动提交。我猜您不希望通过在字段中按回车来提交表单。 - 顺便说一句:今年在 JAX 见? Thomas:有没有一种简单的方法可以在输入时禁用提交(可能没有 javascript,如 BalusCs 的答案)?是的,我将在美因茨的 Jax。 Primefaces 还将包含一个 DefaultCommand 组件,刚刚在 primefaces 博客 (blog.primefaces.org/?p=1787) 上宣布。 【参考方案1】:

这不是 JSF 特有的。这是特定于 html 的。 HTML5 forms specification section 4.10.22.2 基本上指定“树顺序”中第一个出现的 &lt;input type="submit"&gt; 元素与 HTML DOM 树中的当前输入元素 &lt;form&gt; 相同,将在按下回车时调用。

基本上有两种解决方法:

使用 JavaScript 捕捉回车键按下并调用所需的按钮。

<h:form onkeypress="if (event.keyCode == 13)  document.getElementById('formid:saveid').click(); return false; ">

如果表单中有 textarea,则希望将 JS 放在所有非 textarea 输入元素上,而不是放在表单上。另见Prevent users from submitting a form by hitting Enter。


交换 HTML 中的按钮并使用 CSS 浮动将它们交换回来。

<div style="width: 100px; clear: both;">
    <h:commandButton action="#bean.save" value="Save" style="float: right;" />
    <h:commandButton action="#bean.reset" value="Reset" style="float: left;" />
</div>

它可能只需要一些像素微调。当然把CSS放在自己的.css文件中;使用style 是不好的做法,上面的例子是为了简洁。


如果您碰巧使用 PrimeFaces,从 3.2 开始,您可以使用 &lt;p:defaultCommand&gt; 以声明方式标识在表单中按回车键时应调用的按钮。

<h:form>
    <p:defaultCommand target="save" />
    ...
    <h:commandButton id="reset" action="#bean.reset" value="Reset" />
    <h:commandButton id="save" action="#bean.save" value="Save" />
</h:form>

它在幕后使用 JavaScript 将 keydown 监听器附加到父 &lt;h:form&gt; 上,后者依次检查是否在非文本区域/按钮/链接元素中按下了 enter 键,然后调用 @987654334 @ 在目标元素上。与此答案中提到的第一个解决方法基本相同。

【讨论】:

谢谢,我稍微修改了 javascript 以仅在文本输入字段上执行,否则在任何按钮具有焦点时按 enter 也会执行保存操作。修改后的处理程序如下所示:if (event.keyCode == 13 &amp;&amp; event.target.nodeName == 'INPUT' &amp;&amp; event.target.getAttribute('type') == 'text') document.getElementById('form:saveButton').click(); return false; 我注意到 defaultCommand 在 keydown 上执行 - 有没有办法将其更改为 keyup?我们遇到了一个问题,如果有时按下回车键,我们的表单会被多次提交 - 并非总是如此。【参考方案2】:

我找到了一种不那么笨拙且效果很好的方法。这个想法是隐藏的commandButton

很遗憾,display:none 样式无法使用,因为 commandButton 将被忽略。 visibility:hidden 不好,因为它保留了组件的空间。

但我们可以使用以下 CSS 微调样式,使其视觉外观的大小为零

.zeroSize 
    visibility: hidden;
    padding: 0px;
    margin: 0px;
    border: 0px;
    width: 0px;
    height: 0px;

现在只需要:

<h:commandButton value="" action="#bean.save" class="zeroSize" />

这将导致一个不可见的命令按钮,根据 first-next-submit-button 规则可以激活。

【讨论】:

当你使用标签按钮时,这不是焦点吗? @JasperdeVries 不,它不可见,因为它不可见 (visibility:hidden;)。 该解决方案 IMO 比已批准的解决方案更好,因为它以更少的努力解决了问题所涉及的问题。【参考方案3】:

要隐藏元素,您可以使用 css:style="visibility: hidden"

如果您使用 primefaces,要更改默认操作,您可以使用:&lt;p:defaultCommand target="yourButtonDefault" /&gt; 例如:

<h:form id="form">

    <h:panelGrid columns="3" cellpadding="5">
        <h:outputLabel for="name" value="Name:" style="font-weight:bold"/>
        <p:inputText id="name" value="#defaultCommandBean.text" />
        <h:outputText value="#defaultCommandBean.text" id="display" />
    </h:panelGrid>

    <p:commandButton value="Button1" id="btn1" actionListener="#defaultCommandBean.btn1Submit" ajax="false"/>
    <p:commandButton value="Button2" id="btn2" actionListener="#defaultCommandBean.btn2Submit" />
    <h:commandButton value="Button3" id="btn3" actionListener="#defaultCommandBean.btn3Submit" />

    <p:defaultCommand target="btn3" />

</h:form>

来源:Primefaces new component: DefaultCommand

【讨论】:

将它与 结合使用,你会摇滚! 请注意,如果您想阻止表单被提交,请确保删除所有出现的p:defaultCommand 我注意到 defaultCommand 在 keydown 上执行 - 有没有办法将其更改为 keyup?我们遇到了一个问题,如果有时按下回车键,我们的表单会被多次提交 - 并非总是如此。【参考方案4】:

按照 BalusC 使用 JavaScript 解决问题的建议,我编写了一些 jQuery 代码来完成这项工作:

$(function()
  $('form').on('keypress', function(event)
    if(event.which === 13 && $(event.target).is(':input'))
        event.preventDefault();
        $('#save').trigger('click');
    
  );
);

代码笔:http://codepen.io/timbuethe/pen/AoKJj

【讨论】:

【参考方案5】:

仅在文本输入字段中忽略 ENTER 键 (source):

<script type="text/javascript"> 

  function stopRKey(evt)  
     var evt = (evt) ? evt : ((event) ? event : null); 
     var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); 
     if ((evt.keyCode == 13) && (node.type=="text"))  return false; 
   

  document.onkeypress = stopRKey; 

</script>

【讨论】:

【参考方案6】:

您可以将h:commandLink 用作第一个按钮,并使用h:commandButton 之类的css 对其进行样式设置。

例如,引导程序 "btn btn-default" 在 commandLink 和 commandButton 上看起来相同。

【讨论】:

以上是关于在表单中按 Enter 时执行的默认操作的主要内容,如果未能解决你的问题,请参考以下文章

如何禁止按回车键提交表单

如何禁止按回车键提交表单

在 react-testing-library 中按 Enter 提交表单不起作用

由于隐藏按钮,Enter 无法在 IE 中提交表单

当按下默认插入记录按钮 oracle 表单时触发

处理未处理的回车键 c#