60

I've got a jsf 1.2 form with two buttons and several input fields. The first button discards the entered values and repopulates the page with values from a db, the second button saves the entered values. The problem occurs when the user presses enter while the cursor is in one of the input fields, the form gets submitted and the action associated with the first button gets executed.

The code looks like this:

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

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

Is it possible to declare a specific button as the default action when pressing enter? Is this behaviour actually specified somewhere?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Jörn Horstmann
  • 33,639
  • 11
  • 75
  • 118
  • 1
    Trinidad provides such a functionality within it's form tag. [link](http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_form.html) – lkdg Mar 30 '11 at 11:59
  • Hi Jörn, I'd disable autosubmit for forms with just one input field. I guess you don't want the form to be submitted by pressing return in the field. - btw: see you at JAX this year? – Thomas Mar 30 '11 at 12:04
  • Thomas: Is there an easy way to disable submit on enter (perhaps without javascript as in BalusCs answer)? And yes, I will be at Jax in Mainz. – Jörn Horstmann Mar 30 '11 at 12:56
  • 3
    Primefaces is also going to include a `DefaultCommand` component, just announced on the primefaces blog (http://blog.primefaces.org/?p=1787). – Jörn Horstmann Feb 28 '12 at 21:05

6 Answers6

115

This is not specific to JSF. This is specific to HTML. The HTML5 forms specification section 4.10.22.2 basically specifies that the first occuring <input type="submit"> element in the "tree order" in same <form> as the current input element in the HTML DOM tree will be invoked on enter press.

There are basically two workarounds:

  • Use JavaScript to capture the enter key press and invoke the desired button.

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

    If you have textareas in the form, you'd like to put the JS on all non-textarea input elements instead of on the form. See also Prevent users from submitting a form by hitting Enter.


  • Swap the buttons in HTML and use CSS floats to swap them back.

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

    It may only require some pixel finetuning. Of course put CSS in its own .css file; using style is poor practice, the above example is for brevity.


If you happen to use PrimeFaces, since 3.2 you can use <p:defaultCommand> to declaratively identify the button which should be invoked when pressing enter key within the form.

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

It's under the covers using JavaScript for that which attaches a keydown listener to the parent <h:form> which in turn checks if the enter key is pressed in a non-textarea/button/link element, and then invokes click() on the target element. Basically the same as 1st mentioned workaround in this answer.

Nicola Isotta
  • 202
  • 3
  • 10
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 8
    Thanks, I modified the javascript a bit to only execute on text input fields, otherwise pressing enter while any button has the focus would also execute the save action. The modified handler looks like this: `if (event.keyCode == 13 && event.target.nodeName == 'INPUT' && event.target.getAttribute('type') == 'text') { document.getElementById('form:saveButton').click(); return false; }` – Jörn Horstmann Mar 30 '11 at 12:44
  • I note that defaultCommand executes on keydown - is there a way to change it to keyup? We are having a problem where our form is being submitted many times if the enter key is held down sometimes - not always. – BigMac66 Feb 26 '18 at 16:40
10

I found a way which is less hacky and works well. The idea is a hidden commandButton.

Unfortunately display:none style cannot be used because then the commandButton will be ignored. visibility:hidden is not good because it keeps the component's space reserved.

But we can fine tune the style so the size of its visual appearance will be zero with the following CSS:

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

And now all it takes is:

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

This will result in an invisible command button which according to the first-next-submit-button rule can be activated.

icza
  • 389,944
  • 63
  • 907
  • 827
5

To hide elements you can use css: style="visibility: hidden"

To change the default action if you use primefaces, you can use: <p:defaultCommand target="yourButtonDefault" /> For example:

<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

Cristian Arteaga
  • 450
  • 7
  • 11
  • Use this in combination with the and you will rock! – Dimitri Dewaele Mar 12 '15 at 10:09
  • Note that in case you want to **prevent** forms being submitted, make sure to remove all `p:defaultCommand` occurrences. – Jasper de Vries Apr 26 '17 at 12:57
  • I note that defaultCommand executes on keydown - is there a way to change it to keyup? We are having a problem where our form is being submitted many times if the enter key is held down sometimes - not always. – BigMac66 Feb 26 '18 at 16:44
3

Following BalusC's recommendation to solve the problem using JavaScript, I wrote some jQuery code to do the job:

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

Tim Büthe
  • 62,884
  • 17
  • 92
  • 129
3

Ignore the ENTER key only in text input fields (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>
Sergey Chepurnov
  • 1,397
  • 14
  • 23
0

You can use a h:commandLink for the first button and style it with css like the h:commandButton.

For Example bootstraps "btn btn-default" look the same on commandLink and commandButton.

Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
Stefan
  • 1
  • 1