在表单中按下回车键时执行的默认操作

60

我有一个带有两个按钮和几个输入框的jsf 1.2表单。第一个按钮放弃了输入的值,并重新填充页面,使用数据库中的值,第二个按钮保存了输入的值。问题发生在用户在其中一个输入字段中鼠标光标处于活动状态时按下回车键,表单被提交并执行与第一个按钮关联的操作。

代码看起来像这样:

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

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

当按下回车键时,是否可以将特定按钮声明为默认操作?这种行为是否有明确定义?


1
Trinidad 在其表单标签中提供了这样的功能。链接 - lkdg
嗨Jörn,我会为只有一个输入字段的表单禁用自动提交。我猜你不希望在字段中按回车键提交表单。顺便说一句:今年JAX见? - Thomas
Thomas:有没有一种简单的方法可以禁用回车键提交(也许不需要像BalusCs答案那样使用JavaScript)?是的,我将会在Mainz的Jax大会上。 - Jörn Horstmann
3
Primefaces也将包含一个DefaultCommand组件,该组件刚刚在Primefaces博客上宣布(http://blog.primefaces.org/?p=1787)。 - Jörn Horstmann
6个回答

115
这并不是特定于JSF的问题,而是HTML的规范。根据HTML5表单规范4.10.22.2节,在HTML DOM树中与当前输入元素在同一<form>中的第一个出现的<input type="submit">元素将在按下回车键时被调用。
基本上有两种解决方法:
  • 使用JavaScript捕获回车键按下事件并调用所需的按钮。

      <h:form onkeypress="if (event.keyCode == 13) { document.getElementById('formid:saveid').click(); return false; }">
    
    如果您在表单中有多个文本框,您想将JS放在所有非文本框输入元素上,而不是放在表单上。另请参见防止用户按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以来,您可以使用<p:defaultCommand>在表单内按下Enter键时声明性地标识应该被调用的按钮。

<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来完成这个功能,通过为父级<h:form>添加keydown监听器,检查非文本区域/按钮/链接元素是否按下enter键,然后在目标元素上调用click()。基本上与此答案中提到的第一种解决方法相同。


8
谢谢,我稍微修改了 JavaScript 代码,使其只在文本输入框中执行,否则当任何按钮拥有焦点时按下回车键也会执行保存操作。修改后的处理程序如下所示:if (event.keyCode == 13 && event.target.nodeName == 'INPUT' && event.target.getAttribute('type') == 'text') { document.getElementById('form:saveButton').click(); return false; } - Jörn Horstmann
我注意到默认命令在按下键时执行 - 有没有办法将其更改为松开键?我们遇到了一个问题,如果有时按住回车键,我们的表单会被提交多次 - 而不总是。 - BigMac66

10

我找到了一种比较好且有效的方法,思路是使用一个隐藏的commandButton

不幸的是,不能使用display:none样式,因为这样会忽略commandButtonvisibility:hidden也不好,因为它会保留组件的空间。

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

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

现在所需要的只是:

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

这将导致一个看不见的命令按钮,根据第一个-下一个-提交按钮规则可以被激活。


当您使用Tab键时,这不会占用焦点吗? - Jasper de Vries
1
@JasperdeVries 不,它不会因为不可见 (visibility:hidden;) 而影响。 - icza
1
在我看来,这个解决方案比那个已批准的更好,因为它以更少的努力精确地解决了问题所涉及的问题。 - foo

5

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

如果您使用primefaces,可以使用以下方法更改默认操作:<p:defaultCommand target="yourButtonDefault" /> 例如:

<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>

Source: Primefaces new component: DefaultCommand


将此与<p:focus>结合使用,你会非常出色! - Dimitri Dewaele
请注意,如果您想要防止表单被提交,请确保删除所有的p:defaultCommand出现。 - Jasper de Vries
我注意到defaultCommand在keydown时执行 - 有没有办法将其更改为keyup?我们遇到了一个问题,如果有时按住回车键,我们的表单会被提交多次 - 而不总是。 - BigMac66

3

仅在文本输入字段中忽略“ENTER”键(来源):

<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>

3

根据BalusC的建议,为了解决问题,我编写了一些jQuery代码:

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

CodePen: http://codepen.io/timbuethe/pen/AoKJj


0
你可以使用 h:commandLink 作为第一个按钮,并且像 h:commandButton 一样使用 CSS 来设置样式。
例如,Bootstrap 中的 "btn btn-default" 在 commandLink 和 commandButton 上看起来相同。

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