jsf - pulsar - Acción predeterminada para ejecutar al presionar enter en un formulario
javascript no enviar formulario al pulsar enter (6)
Tengo un formulario jsf 1.2 con dos botones y varios campos de entrada. El primer botón descarta los valores ingresados y vuelve a llenar la página con valores de un db, el segundo botón guarda los valores ingresados. El problema ocurre cuando el usuario presiona enter mientras el cursor se encuentra en uno de los campos de entrada, se envía el formulario y se ejecuta la acción asociada con el primer botón.
El código se ve así:
<h:commandButton action="#{bean.reset}" value="Reset" />
<h:commandButton action="#{bean.save}" value="Save" />
<!-- h:datatable with several h:inputText elements -->
¿Es posible declarar un botón específico como acción predeterminada al presionar enter? ¿Este comportamiento está realmente especificado en alguna parte?
Encontré un camino que es menos hacky y funciona bien. La idea es un commandButton
oculto.
Desgraciadamente display:none
se puede usar display:none
estilo porque entonces se commandButton
el commandButton
. visibility:hidden
no es bueno porque mantiene el espacio reservado del componente.
Pero podemos ajustar el estilo para que el tamaño de su apariencia visual sea cero con el siguiente CSS:
.zeroSize {
visibility: hidden;
padding: 0px;
margin: 0px;
border: 0px;
width: 0px;
height: 0px;
}
Y ahora todo lo que se necesita es:
<h:commandButton value="" action="#{bean.save}" class="zeroSize" />
Esto dará como resultado un botón de comando invisible que de acuerdo con la regla del primer botón siguiente se puede activar.
Esto no es específico de JSF. Esto es específico de HTML. La sección de especificación de formas HTML5 4.10.22.2 básicamente especifica que el primer elemento <input type="submit">
aparece en la "orden de árbol" en la misma <form>
que el elemento de entrada actual en el árbol HTML DOM se invocará al presionar enter .
Básicamente hay dos soluciones:
Use JavaScript para capturar la tecla enter, presione e invoque el botón deseado.
<h:form onkeypress="if (event.keyCode == 13) { document.getElementById(''formid:saveid'').click(); return false; }">
Si tiene áreas de texto en el formulario, le gustaría poner el JS en todos los elementos de entrada que no sean de texto en lugar de en el formulario. Consulte también Evitar que los usuarios envíen un formulario presionando Enter .
Cambie los botones en HTML y use flotantes CSS para intercambiarlos.
<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>
Es posible que solo requiera algunos ajustes de píxeles. Por supuesto, ponga CSS en su propio archivo
.css
; usar elstyle
es una práctica pobre, el ejemplo anterior es por brevedad.
Si usa PrimeFaces, desde 3.2 puede usar <p:defaultCommand>
para identificar declarativamente el botón que debe invocarse al presionar la tecla enter dentro del formulario.
<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>
Está bajo las cubiertas que usan JavaScript para eso que conecta un oyente keydown
al padre <h:form>
que a su vez verifica si se presiona la tecla enter en un elemento no textarea / button / link, y luego invoca click()
en el elemento objetivo Básicamente lo mismo que la primera solución mencionada en esta respuesta.
Ignore la tecla ENTER solo en campos de entrada de texto ( 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>
Para ocultar elementos, puede usar css: style="visibility: hidden"
Para cambiar la acción predeterminada si usa Primefaces, puede usar: <p:defaultCommand target="yourButtonDefault" />
Por ejemplo:
<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>
Fuente: blog.primefaces.org/?p=1787
Puede usar un h:commandLink
para el primer botón y darle un estilo con css como h:commandButton
.
Por ejemplo bootstraps "btn btn-default"
tienen el mismo aspecto en commandLink y commandButton.
Siguiendo la recomendación de BalusC de resolver el problema usando JavaScript, escribí un código jQuery para hacer el trabajo:
$(function(){
$(''form'').on(''keypress'', function(event){
if(event.which === 13 && $(event.target).is('':input'')){
event.preventDefault();
$(''#save'').trigger(''click'');
}
});
});