Ajax4Jsf <a4j:form data=”broken!”>
A4J:Form is missing several specified ajax functions
(View this issue on the JBoss tracker here. Keep reading, there is a fix… download fix)The issue:
When using the a4j:form component, the data=”#{managedBean.property}” the properties defined in the data element list are supposed to be available after the a4j event in the data JavaScript variable; however, with <a4j:form> the attribute is not correctly causing the JavaScript data variable to be populated. The data variable is always undefined, even if the managed bean property is set to a valid value. This is exhibited by the alert box as the value is displayed, “(undefined)”.Example:
—-
The workaround:
Taking a look at the source code revealed that the <a4j:form> was not in fact including this behavior at all in the broadcast() method, which is where the data element processing occurs in the <a4j:commandButton>.UIAjaxForm.broadcast()
/* (non-Javadoc) * @see javax.faces.component.UIComponentBase#broadcast(javax.faces.event.FacesEvent) */ public void broadcast(FacesEvent event) throws AbortProcessingException { // perform default super .broadcast(event); if (event instanceof AjaxEvent) { // complete re-Render fields. AjaxEvent deliver before render response. setupReRender(); } } |
—-
In fact, however, if we modify the <a4j:form> broadcast() method to behave like its <a4j:commandButton> relative, we can still achieve this functionality!Updated: UIAjaxForm.broadcast()
public void broadcast(final FacesEvent event) throws AbortProcessingException { super.broadcast(event); if (event instanceof AjaxEvent) { this.setupReRender(); Object data = this.getData(); AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context); if (null != data) { ajaxContext.setResponseData(data); } String focus = this.getFocus(); if (null != focus) { UIComponent focusComponent = RendererUtils.getInstance().findComponentFor(this, focus); if (null != focusComponent) { focus = focusComponent.getClientId(context); } ajaxContext.getResponseDataMap().put(AjaxActionComponent.FOCUS_DATA_ID, focus); } ajaxContext.setOncomplete(this.getOncomplete()); } } |
—-
We’re set! I don’t particularly like to repeat this code, so I may get around to refactoring everything and submitting it back to the Ajax4JSF project. For now, though, this blog will have to do. I believe other functionality that was also broken included both the focus=”elementId” and the oncomplete=”javascriptCode”. As always, please feel free to improve and comment on this. Enjoy!Posted in JSF, OpenSource