[
http://jira.jboss.com/jira/browse/RF-2393?page=comments#action_12401592 ]
Mike Hanafey commented on RF-2393:
----------------------------------
This bug can be reproduced in a very simple test case, and it can be easily fixed,
although it is not clear to me if this "fix" would introduce other problems.
The fix is:
class org.ajax4jsf.component.UIDataAdaptor, method public void broadcast(FacesEvent event)
as the following conditional:
if (!(rowEvent.getPhaseId() == PhaseId.RENDER_RESPONSE)) {
this._ajaxRowKey = eventRowKey;
// this._ajaxRowKeysMap.put(getBaseClientId(faces), eventRowKey);
}
When the validation failure occurs in the inner tree, "this._ajaxRowKey" is
never set, which means the UITree does not add the necessary client ids to the rendered
areas set. If this condition on RENDER_RESPONSE phase is removed, the test case works as
expected. Presumably the condition was put there for a good reason, but for the test case
it does harm without doing any good that I can see.
The following diff shows the additional client ids in the "Ajax-Update-Ids"
wiith the fix in place --
% diff withoutfix.txt withfix.txt
7a8,9
Sequence:SeqTree:0:0:s
Sequence:SeqTree:0:0:s:childs
10a13,14
Sequence:SeqTree:input
Sequence:SeqTree:script
Included below is a simpler view that does not use Facelet includes. In this case the
inner tree does not collapse, but the bug shows up because the validation errors are not
displayed:
--------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:gx="http://genomix.es.dupont.com/faces/core"
xmlns:trak="http://genomix.es.dupont.com/faces/trak">
<head>
<link rel="stylesheet" type="text/css"
href="../CSS/common.css"/>
</head>
<ui:composition template="/templates/main.xhtml">
<ui:define name="title">Trak:Search:LeadView</ui:define>
<ui:define name="headerSection">
<link rel="stylesheet" type="text/css"
href="../CSS/tags/leadViewHeader.css"/>
<link rel="stylesheet" type="text/css"
href="../CSS/tags/comment.css"/>
<link rel="stylesheet" type="text/css"
href="../CSS/tags/sequence.css"/>
<script type="text/javascript">
function GXmakeVisible(id) {
var e = document.getElementById(id);
if (e) {
e.scrollIntoView();
}
}
</script>
</ui:define>
<ui:define name="body">
<h:form id="Sequence">
<rich:tree id="CmtTree" var="citem"
value="#{leadReport.lead.commentaryUiTree.rootNode}"
switchType="client"
nodeFace="#{citem.nodeFace}"
adviseNodeOpened="#{leadReport.adviseNodeOpened}"
toggleOnClick="false" rendered="false">
<!--@elvariable id="citem"
type="genomix.tractor.CommentUiTree.CommentUi"-->
<rich:treeNode id="top" type="top"
nodeClass="C-wrappingTreeNode">
<a4j:commandButton id="addTopComm" immediate="true"
image="/images/element_add-24x24.png" alt="ADD"
actionListener="#{leadReport.lead.commentaryUiTree.actionListenerAddTopComment}"
reRender="CmtTree"
title="Add a new TOP LEVEL comment."
style="vertical-align: middle;"
oncomplete="GXmakeVisible('Commentary:CmtTree:0:#{citem.addTopCommentNodeId}:ec')"/>
<a4j:commandButton id="topSaveButton"
immediate="true" value="Ajax Save" reRender="CmtTree"
title="#{msg['act.save']}"/>
<h:outputText value="#{citem.rootData}"/>
<trak:message for="addTopComm"/>
</rich:treeNode>
<rich:treeNode id="c" type="c"
nodeClass="C-wrappingTreeNode">
<trak:comment id="cmtNode"
lead="#{leadReport.lead}" cmt="#{citem}"
reRender="CmtTree"/>
</rich:treeNode>
<rich:treeNode id="ec" type="ec"
nodeClass="C-wrappingTreeNode">
<table class="C-vmargin COMMENT">
<tr class="COMMENT-title">
<td colspan="3">
<h:inputText id="title"
value="#{citem.appData.title}" required="true"
validator="#{citem.validateTitle}"
styleClass="COMMENT-input">
<gx:trimString/>
</h:inputText>
<rich:message for="title"/>
</td>
</tr>
<tr class="COMMENT-body">
<td colspan="3">
<h:inputTextarea id="body"
value="#{citem.appData.body}" required="true"
validator="#{citem.validateTitle}"
rows="4"
styleClass="COMMENT-input">
<gx:trimString/>
</h:inputTextarea>
<rich:message for="body"/>
</td>
</tr>
<tr class="COMMENT-footer">
<td>
<a4j:commandButton id="saveButton"
value="Ajax Save" actionListener="#{citem.actionListenerSaveComment}"
reRender="CmtTree"
title="#{msg['act.save']}"/>
<h:commandButton id="saveButtonNA"
value="Plain Save"
actionListener="#{citem.actionListenerSaveComment}"
title="#{msg['act.save']}"/>
<a4j:commandButton id="nothingButton"
value="Ajax Immediate" immediate="true"
actionListener="#{citem.actionListenerNothing}" reRender="CmtTree"
title="#{msg['act.save']}"/>
<a4j:commandButton id="quitButton"
value="Ajax Quit" actionListener="#{citem.actionListenerQuitComment}"
immediate="true"
reRender="CmtTree"
title="#{msg['act.quit']}" style="margin-left:8px"/>
<rich:message for="saveButton"/>
<rich:message for="saveButtonNA"/>
<rich:message for="quitButton"/>
</td>
<td/>
<td class="COMMENT-whoWhen">By:
#{citem.appData.whoWhen.namesAndDates}</td>
</tr>
</table>
</rich:treeNode>
</rich:tree>
<rich:tree id="SeqTree" var="sitem"
value="#{leadReport.lead.sequenceUiTree.rootNode}"
switchType="client"
nodeFace="#{sitem.nodeFace}"
adviseNodeOpened="#{leadReport.adviseNodeOpened}"
toggleOnClick="false" rendered="true">
<!--@elvariable id="sitem"
type="genomix.tractor.SequenceUiTree.SequenceUi"-->
<rich:treeNode id="top" type="top"
nodeClass="C-wrappingTreeNode">
<h:outputText value="#{sitem.rootData}"/>
</rich:treeNode>
<rich:treeNode id="s" type="s"
nodeClass="C-wrappingTreeNode">
<rich:tree id="CmtTree" var="citem"
value="#{leadReport.lead.commentaryUiTree.rootNode}"
switchType="client"
nodeFace="#{citem.nodeFace}"
adviseNodeOpened="#{leadReport.adviseNodeOpened}"
toggleOnClick="false">
<!--@elvariable id="citem"
type="genomix.tractor.CommentUiTree.CommentUi"-->
<rich:treeNode id="top" type="top"
nodeClass="C-wrappingTreeNode">
<a4j:commandButton id="addTopComm"
immediate="true" image="/images/element_add-24x24.png"
alt="ADD"
actionListener="#{leadReport.lead.commentaryUiTree.actionListenerAddTopComment}"
reRender="CmtTree"
title="Add a new TOP LEVEL comment."
style="vertical-align: middle;"
oncomplete="GXmakeVisible('Commentary:CmtTree:0:#{citem.addTopCommentNodeId}:ec')"/>
<a4j:commandButton id="topSaveButton"
immediate="true" value="Ajax Save" reRender="CmtTree"
title="#{msg['act.save']}"/>
<h:outputText value="#{citem.rootData}"/>
<trak:message for="addTopComm"/>
</rich:treeNode>
<rich:treeNode id="c" type="c"
nodeClass="C-wrappingTreeNode">
<trak:comment id="cmtNode"
lead="#{leadReport.lead}" cmt="#{citem}"
reRender="CmtTree"/>
</rich:treeNode>
<rich:treeNode id="ec" type="ec"
nodeClass="C-wrappingTreeNode">
<table class="C-vmargin COMMENT">
<tr class="COMMENT-title">
<td colspan="3">
<h:inputText id="title"
value="#{citem.appData.title}" required="true"
validator="#{citem.validateTitle}"
styleClass="COMMENT-input">
<gx:trimString/>
</h:inputText>
<rich:message for="title"/>
</td>
</tr>
<tr class="COMMENT-body">
<td colspan="3">
<h:inputTextarea id="body"
value="#{citem.appData.body}" required="true"
validator="#{citem.validateTitle}"
rows="4"
styleClass="COMMENT-input">
<gx:trimString/>
</h:inputTextarea>
<rich:message for="body"/>
</td>
</tr>
<tr class="COMMENT-footer">
<td>
<a4j:commandButton id="saveButton"
value="Ajax Save" actionListener="#{citem.actionListenerSaveComment}"
reRender="CmtTree"
title="#{msg['act.save']}"/>
<h:commandButton id="saveButtonNA"
value="Plain Save"
actionListener="#{citem.actionListenerSaveComment}"
title="#{msg['act.save']}"/>
<a4j:commandButton id="nothingButton"
value="Ajax Immediate" immediate="true"
actionListener="#{citem.actionListenerNothing}" reRender="CmtTree"
title="#{msg['act.save']}"/>
<a4j:commandButton id="quitButton"
value="Ajax Quit" actionListener="#{citem.actionListenerQuitComment}"
immediate="true"
reRender="CmtTree"
title="#{msg['act.quit']}" style="margin-left:8px"/>
<rich:message for="saveButton"/>
<rich:message for="saveButtonNA"/>
<rich:message for="quitButton"/>
</td>
<td/>
<td class="COMMENT-whoWhen">By:
#{citem.appData.whoWhen.namesAndDates}</td>
</tr>
</table>
</rich:treeNode>
</rich:tree>
</rich:treeNode>
</rich:tree>
</h:form>
<h:form id="clear">
<h:commandButton id="clearSession" value="Invalidate
Session"
actionListener="#{leadReport.actionListenerInvalidateSession}"/>
<h:commandButton id="submit" value="Submit"
actionListener="#{leadReport.actionListenerSubmit}"/>
</h:form>
</ui:define>
</ui:composition>
</html>
-------------------------------------------------------------------------------------------------------------------
Tree nested inside node of an outer tree has strange behaviour on
ajax submit when there are validation errors
--------------------------------------------------------------------------------------------------------------
Key: RF-2393
URL:
http://jira.jboss.com/jira/browse/RF-2393
Project: RichFaces
Issue Type: Bug
Affects Versions: 3.1.4
Environment: Glassfish v2, JSF RI 1.2
Reporter: Mike Hanafey
Assigned To: Nick Belaevski
Fix For: 3.2.0
Attachments: NestedTree.tar.gz, NestedTree.war
I have situation where there is an outer tree whose nodes have an inner tree.
Specifically, the outer tree is over DNA sequences, and each DNA sequence may have a tree
of comments attached to it.
Both the inner and outer trees have a couple of faces, one is used when a node is in
display mode, and the other when it is in edit mode.
If the inner tree is put into edit mode at a node (via an ajax request) and a validation
error occurs on a second ajax request to submit the edits, the whole inner tree for that
node disappears. It can be recovered by doing a browser redisplay. If there is no
validation error, the edit works as expected
Looking at the XmlHttpRequest response when there is a validation error shows that the
response does not contain the expected tree nodes.
When this same comment tree code (both the backing beans and the facelets views) is
applied on an unnested tree this problem does not occur.
A test war is attached (the war is big only because it includes the library dependencies
-- the test code itself is small).
To demonstrate, deploy the war and look at the top page.
Click on the + next to "Comments" (this is the un-nested tree). Click
"Ajax Save". Observe the "Value is required" messages.
Enter something into the first textfield, and do the "Ajax Save". Now a custom
validation message appears.
Now for the first strangeness. Enter something in both the textfield and the textarea.
The custom validation message appears on both inputs, but now the inputs just made are
erased. When only one of these fields have data, the data entered in the other field is
preserved, and I believe the clearing of input data is another error, but not the one in
the title of this this issue.
To see the main issue, open the tree labeled "Sequences". This has a comments
tree just like the one above nested inside the sequence node.
Click on the + next the "Comments" under "Sequences".
Click on "Ajax Save". Now instead of seeing the "Value is required"
error, the inner tree node collapses. Click on the "Submit" button, an reopen
the "Sequences" tree to see that the inner tree is in fact still intact.
Click on "Ajax Immediate". Now the tree does not collapse. The only difference
is this button is immediate, so the validation steps are not done.
Finally, clicking on "Plain Save" shows the expected validation errors (now the
Sequence tree collapses after the submit so it must be manually opened, but I guess this
is expected behavior because the open / close state is not maintained across the request).
The problem where the inputs that fail validation are erased remains even with this
non-ajax update mode).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira