I have a Facelets subview at /subviews/document-tree.xhtml
that renders a tree for each tab on a <rich:tabPanel>
client. The page and sub views are based on JSF 2 and RichFaces 4.
<ui:composition ...>
<rich:tree value="#{rootNode}" var="treeNode" id="#{treeId}">
<rich:treeNode ... id="chapternode">
<h:panelGrid columns="2">
<rich:outputText value="#{treeNode.name}" />
<h:commandLink>
<h:graphicImage library="images/icons" name="delete.png" />
<rich:componentControl target="remove-chapter-popup" operation="show" />
</h:commandLink>
<rich:popupPanel modal="true"
onmaskclick="#{rich:component('remove-chapter-popup')}.hide(); return false;"
id="remove-chapter-popup">
<f:facet name="header">
<h:outputText value="Remove chapter?" />
</f:facet>
<f:facet name="controls">
<h:outputText value="X" />
</f:facet>
<p>Remove chapter #{treeNode.name}?</p>
<h:panelGrid columns="2">
<h:commandButton value="Add"
action="#{nodeManager.removeChapterNode(treeNode)}"
onclick="#{rich:component('remove-chapter-popup')}.hide(); return true;">
<!--f:ajax execute="@this" render="@form" /--> <!-- never executed! -->
<a4j:ajax execute="@this" render="@form" /> <!-- this works however! -->
</h:commandButton>
<h:commandButton value="Cancel"
onclick="#{rich:component('remove-chapter-popup')}.hide(); return false;" immediate="true" />
</h:panelGrid>
</rich:popupPanel>
</h:panelGrid>
</rich:treeNode>
...
</rich:tree>
</ui:composition>
This basically shows tree nodes with their name plus an image to the right for deletion.
Each tree sub view is placed into a <rich:tab>
, so the tab panel does have the required enclosing <h:form>
. There are no other nested forms (forbidden anyway).
The #{nodeManager.removeChapterNode(treeNode)}
bean was correctly marked as @ViewScoped
.
Now what happens is kinda strange:
When using <f:ajax execute="@this" ... />
the button never executes, whereas using <a4j:ajax execute="@this" ... />
always works.
Why? What's wrong here?
It doesn't make much sense, given the fact that RichFaces <a4j:ajax>
is based 100% on JSF 2 <f:ajax>
according to their own words.
Could it be a bug in JSF 2.1.7, which I'm using? (the implementation that came with JBoss AS 7.1.1.Final)
Here's the reduced diff:
<form id="tree-form" name="tree-form" method="post" action="/pqgenerator2/debug.jsf" enctype="application/x-www-form-urlencoded">
...
<table style="margin: 0 auto;">
<tbody>
<tr>
- <td><input id="tree-form:sorting-tree-one:real root:j_idt34" type="submit" name="tree-form:sorting-tree-one:real root:j_idt34" value="Fortfahren" onclick="jsf.util.chain(this,event,'RichFaces.$(\'tree-form:sorting-tree-one:real root:add-root-chapter-popup\').hide(); return true;','mojarra.ab(this,event,\'action\',\'@this tree-form:sorting-tree-one:real root:new-root-chapter-name-input\',\'@form\')');return false" /></td>
+ <td><input id="tree-form:sorting-tree-one:real root:j_idt34" type="submit" name="tree-form:sorting-tree-one:real root:j_idt34" value="Fortfahren" onclick="jsf.util.chain(this,event,'RichFaces.$(\'tree-form:sorting-tree-one:real root:add-root-chapter-popup\').hide(); return true;','RichFaces.ajax(this,event,{"parameters":{"javax.faces.behavior.event":"action","org.richfaces.ajax.component":"tree\\u002Dform:sorting\\u002Dtree\\u002Done:real root:j_idt34"} ,"sourceId":this} )');return false" /></td>
</tr>
</tbody>
</table>
...
- </div></span></span></div></div><input type="hidden" name="tree-form:sorting-tree-one__SELECTION_STATE" id="tree-form:sorting-tree-one__SELECTION_STATE" class="rf-tr-sel-inp" value="" /><script type="text/javascript">new RichFaces.ui.Tree("tree\u002Dform:sorting\u002Dtree\u002Done",{"toggleType":"client"} );</script></div></div><script type="text/javascript">new RichFaces.ui.Tab("tree\u002Dform:j_idt21",{"index":0,"leave":null,"togglePanelId":"tree\u002Dform:tree\u002Dtabpanel","switchMode":"client","name":"Blah GmbH","enter":null,"disabled":false} )</script></div><script type="text/javascript">new RichFaces.ui.Tab("tree\u002Dform:j_idt21",{"index":0,"leave":null,"togglePanelId":"tree\u002Dform:tree\u002Dtabpanel","switchMode":"client","name":"Blah GmbH","enter":null,"disabled":false} )</script></div><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="998210192617713914:-9142017502724223608" autocomplete="off" />
+ </div></span></span></div></div><input type="hidden" name="tree-form:sorting-tree-one__SELECTION_STATE" id="tree-form:sorting-tree-one__SELECTION_STATE" class="rf-tr-sel-inp" value="" /><script type="text/javascript">new RichFaces.ui.Tree("tree\u002Dform:sorting\u002Dtree\u002Done",{"toggleType":"client"} );</script></div></div><script type="text/javascript">new RichFaces.ui.Tab("tree\u002Dform:j_idt21",{"index":0,"leave":null,"togglePanelId":"tree\u002Dform:tree\u002Dtabpanel","switchMode":"client","name":"Blah GmbH","enter":null,"disabled":false} )</script></div><script type="text/javascript">new RichFaces.ui.Tab("tree\u002Dform:j_idt21",{"index":0,"leave":null,"togglePanelId":"tree\u002Dform:tree\u002Dtabpanel","switchMode":"client","name":"Blah GmbH","enter":null,"disabled":false} )</script></div><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="-5805340602741883884:1908800949269113937" autocomplete="off" />
</form>
The problem here is that I create a dummy root node for the RichFaces root to be displayed and I add the real root via RichFaces TreeNodeImpl
's addChild("real root", ...)
, which contains a space in the key.
The <a4j:ajax>
code can obviously handle this but not JSF 2's <f:ajax>
(note the first diff part).