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