 |
As the new Java.net infrastructure contains project-level wikis, this main wiki will be shut down in the near future. For wiki page export and general wiki questions please contact the site admin at communitymanager@java.net. Why is the ActionListener on Ajax4jsf commandLink and commandButton not invoked if the rendered attribute refers to a request scope bean?
> Could you explain to me why that backing bean needs to be session
> scoped in order for the action/actionListener method to be invoked
> when rendered is set?
This is like JSF and Request scope work. The logic is in the base
UIComponent class. The decode phase is skipped if the component has
rendered="false". The same for readonly and disabled attributes on the input
components when they equals to false.
This is a quote from the processDecodes method:
....
// Skip processing if our rendered flag is false
if (!isRendered()) { return; }
....
In general, it sounds logically correct. There is no reason to decode
component (taking data received from client) if we do not expect the data
might be changed.
So, the question about rendered attribute. Why it works like it equals to
false, when you truly believe it must equals to true at this moment.
Short answer: because it equals to false, actually.
Why?
Let's examine situation on the simple example:
We have myBackingBean bean in the Request scope. We want the commandButton
appears only in particular condition and assign a myCondition flag on this
bean for that.
At the first moment, the commandButton should not be visible. So, (**) when
the bean is created we set myCondition to false.
For the simplicity reason, let's say we have Ajax link which switch
myCondition from false to true when the link is clicked.
This is what we have on the page:
<a4j:commandLink
action="#{myBackingBean.showButton}"
value="show the button"
reRender="button"
/>
<a4j:outputPanel id="button">
<a4j:commandButton
actionListener="#{myBackingBean.myActionListener}"
reRender="section1"
rendered="#{myBackingBean.myCondition}">
</a4j:commandButton>
</a4j:outputPanel>
If we click on the "show the button" it appears. Then, we click the button
and expert the actionListener will be invoked. Right?
Let's see.
request scope bean is created when request comes. Request scope bean dies
when response is complete (*) . It is a most important statement here.
1. We click the link. The request came. The myBackingBean is created.
myCondition is false at this moment. See ** above
2. on the Invoke Application (5th phase), myBackingBean.showButton sets the
myCondition to true
3. on the RenderResponse (6th phase), the commandButton will be rendered,
because myBackingBean.myCondition returns true using JSF EL
4. the reRendered section went to client and the myBackingBean bean is dead.
See * above
5. We see the button and click on it. The request came. The myBackingBean is
created. myCondition is false at this moment. See ** above
6. on the Decode (3rd phase) isRendered asks for myBackingBean.myCondition
via JSF EL and gets false. The decode is skipped.
Even you use any input component to set myBackingBean.myCondition and it
comes with the same request, the bean is updated with true on the
UpdateModel (4th phase). So, the decode for button is already skipped.
What is different with a Session scope? The Session scope bean stored and
restored back when request come.
So, if we set myCondition to true
previously, it will equals to true on the Decode (3rd phase) when
isRendered makes its judgment.
P.S. As an alternative to Session scope you can use MyFaces t:saveState tag. Also you can use the component binding to manipulate the component state without references to managed bean facility.
-- Main.sergeysmirnov - 22 Feb 2005
|
Topic WhyActionListneterOnTheAjaxCommandLinkAndCommandButtonIsNotInvokedIfRenderedAttributeRefersToRequestScopeBean . {
Edit
| Ref-By
| Printable
| Diffs r3 < r2 < r1
| More
}
|
|