JSF a4j:commandButton not working when 'disabled' is set
ajax4jsf, jakarta-ee, java, jsf, richfaces
Solution
In HTML world, the `disabled` attribute causes the `name`-`value` attribute pair of any HTML input element (`input`, `select`, `textarea` and `button`) not being sent to the server side.
In JSF world, the presense of the `name` attribute is been used to identify the bean action to be invoked at the server side. However, during apply request values phase of the form submit JSF also checks if the component's `disabled` (and `rendered`) attribtue evaluates `true` before taking any actions.
The `#{region}` is here an iterated table row object of `#{MyPageBackingBean.regions}` whose `isMessageEmpty()` getter by default returns `true`. In the new request of the form submit the `#{MyPageBackingBean.regions}` is apparently empty which effectlively makes the button `disabled`. JSF won't invoke the associated action then.
To the point, you need to make sure that `#{MyPageBackingBean.regions}` returns exactly the same datamodel in the subsequent request. Easiest fix is to place the `MyPageBackingBean` bean in session scope so that it don't get reinitialized in the subsequent request, but that has more negative side effects as well. Another fix is to rearrange the datamodel loading so that it happens in the bean constructor. As you're already using Tomahawk's `<t:dataTable>`, you need to set its `preserveDataModel` attribute to `true`. For more hints about using datatables, you may find this article useful as well: Using Datatables.
Problem
When I include a 'disabled' attribute on an a4j:commandButton, the button's action is not performed. Taking the 'disabled' attribute out causes it to work properly. I am not doing any special validation (that I'm aware of) and am not seeing any validation error messages. Here is part of my page: ``` <t:dataTable id="myTable" var="region" value="#{MyPageBackingBean.regions}" width="100%"> ... <a4j:commandButton value="Update" action="#{region.doUpdate}" oncomplete="alert('done');" disabled="#{!empty region && region.messageEmpty}" immediate="true"/> ... </t:dataTable> ``` Any ideas? Thanks! Edit: I tried setting preserveDataModel="true" on the t:dataTable to no avail. I also made a test having an a4j:commandButton and text box with no data table, but the backing bean action is still not being fired: ``` <h:form> <a4j:region> <a4j:outputPanel id="testregion"> <h:messages id="messages"/> <a4j:status> <f:facet name="start"> <h:graphicImage value="/images/progress_indicator.gif"/> </f:facet> </a4j:status> <h:inputTextarea rows="5" value="#{MyPageBackingBean.myValue}" style="width:100%; border: 1px solid #99CCFF;"> <a4j:support event="onkeyup" reRender="testregion" eventsQueue="messageModificationQueue" ignoreDupResponses="true" requestDelay="500"/> </h:inputTextarea> <a4j:commandButton id="doDelete" value="Delete" action="#{MyPageBackingBean.dummy}" reRender="testregion" disabled="#{empty MyPageBackingBean.myValue}"/> <h:outputText value="#{MyPageBackingBean.myValue}"/> </a4j:outputPanel> </a4j:region> </h:form> ``` Here is the new backing bean code used for testing: ``` private String m_myValue = null; public String getMyValue() { return m_myValue; } public void setMyValue(String value) { m_myValue = value; } private String mystr2 = null; public String dummy() { mystr2 = "hello"; return null; } ``` Thanks!