fr13d fr13d - 1 year ago 66
Ajax Question

AJAX removes JSF form event handler

I have a JSF page with a form, with the following 2 somewhat nonstandard requirements:

  1. Some input components are only relevant for certain settings of other inputs. I.e., if a certain value is chosen in a
    , another field should be shown or hidden as appropriate.

    This is handled via a
    <f:ajax render="@form">
    and the
    attribute. Simple.

  2. I need to call some Javscript code on submit and reset before the request is posted to the server.

    This is handled by adding event handlers to the form element for the
    events, via jQuery, in the
    event handler. Not difficult either.

What I however find is that once the AJAX POST request happens, the
event handlers disappear. Obviously the
handler is not activated again, so they are not recreated - but it is strange that they are removed.

Can someone tell me what I am doing wrong, or a better (correct) way to accomplish this?

Basic Facelets page for demonstration purposes:

(no backing bean needed)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<html xmlns=""
<title>Test page</title>
<h:outputScript target="head" library="js" name="jquery.js" />
<h:outputScript target="body">
//Code just for debugging purposes
function debugAjax(data) {
console.log("AJAX onevent. Type=" + data.type + ", Status=" + data.status);
function debugEvents() {
var evs = jQuery._data(document.getElementById('myform'), 'events');
if (evs) {
jQuery.each(evs, function(index, value) {
console.log(" - Event " + index + "=" + value);
} else {
console.log(" - NO EVENTS");

<h:outputScript target="body">
jQuery(document).ready(function() {
console.log("Adding handlers");
reset : function() { console.log("RESET activated"); },
submit : function() { console.log("SUBMIT activated"); }

<h:form id="myform">
<h:panelGrid columns="2">
<h:outputLabel for="formType" value="Form type" />
<h:selectOneMenu id="formType" value="#{formType}">
<f:selectItem itemValue="1" itemLabel="Simple" />
<f:selectItem itemValue="2" itemLabel="With additional data" />
<f:selectItem itemValue="3" itemLabel="Another item" />

<f:ajax render="@form" onevent="debugAjax" />

<ui:remove>conditionally displayed field</ui:remove>
<h:outputLabel for="moreData" value="More data" rendered="#{formType eq '2'}" />
<h:inputText id="moreData" value="#{moreData}" rendered="#{formType eq '2'}" />

<h:commandButton type="reset" id="delete" value="Cancel" />
<h:commandButton type="submit" id="submit" value="OK" />

Console output:

This is the output in my Javascript console (explanations inside {{}} added)

{{Initial load of page}}
GET http://localhost:8080/xxx/test.jsf [HTTP/1.1 200 OK 6ms]
"Adding handlers"
" - Event reset=[object Object]"
" - Event submit=[object Object]"
{{reset/submit event handlers work as expected}}
{{now changing dropdown that fires AJAX}}
POST http://localhost:8080/xxx/test.jsf [HTTP/1.1 200 OK 9ms]
"AJAX onevent. Type=event, Status=begin"
" - Event reset=[object Object]"
" - Event submit=[object Object]"
"AJAX onevent. Type=event, Status=complete"
" - Event reset=[object Object]"
" - Event submit=[object Object]"
"AJAX onevent. Type=event, Status=success"
{{reset/submit event handlers DON'T work, but standard form resetting/submitting still works}}

The test was run from Firefox, GlassFish 4.1 (13) (Mojarra 2.2.7).

Answer Source

The simple answer is that the AJAX call should render only some or all contents inside the form. In the above sample, it would do nicely to give an id to the <h:panelGrid>:

<h:panelGrid id="fieldgrid" columns="2">

... and then render that in the AJAX call:

<f:ajax render="fieldgrid" ... />