[
https://issues.jboss.org/browse/RF-11134?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Val Blant updated RF-11134:
---------------------------
Description:
Please consider the following test code:
{code}
<rich:dataTable id="testTable"
value="#{dataTableTestBackingBean.rowsModel}"
var="rowVar">
<f:facet name="header">
<rich:column>
<h:outputText value="Column 1" />
</rich:column>
</f:facet>
<rich:column>
<h:inputText id="valTest" value="#{rowVar.col1}" >
<a4j:ajax
event="blur"
render="testColumn, footerTest"
limitRender="true"
execute="@this" />
</h:inputText>
</rich:column>
<rich:column>
<h:outputText id="testColumn"
value="#{dataTableTestBackingBean.footerValue}" />
</rich:column>
<f:facet name="footer">
<rich:column>
<h:outputText id="footerTest"
value="#{dataTableTestBackingBean.footerValue}" />
</rich:column>
</f:facet>
</rich:dataTable>
{code}
This example will fail with the following Javascript error in the browser:
{color:red}
{quote}
Error: During update: formId:testTable:0:footerTest not found
{quote}
{color}
This is expected, b/c the correct id for the footer is
_formId:testTable:footerTest_.
The bug is in _org.richfaces.context.ComponentIdResolver_. Here is what happens:
# The _RenderComponentCallback_ is executed on the input component (_'valTest'_
in the example) and it reads the list of short ids to render from the attached
Ajax Behavior. Note that we got here by walking the parent data table model, so
the current rowKey is 0
# _RenderComponentCallback_ asks _ComponentIdResolver_ to resolve short ids
into client IDs
# _ComponentIdResolver_ starts ascending up the tree from _'valTest'_ and
looking at facets and children until it finds _'footerTest'_.
# At this point it asks for the clientId of _'footerTest'_ w/o regard for the
fact that the data model has a rowKey that is set 0
So, we get the wrong id b/c we call UiData.getClientId() outside of the normal
walking order of that model.
*EDIT:*
I noticed that if I nest the above data table in another data iterator, then
the footer update suddenly starts working. I investigated and it turned out
that nested table will have _getClientId()_ called on all of its components by
the parent table, and since _clientId_ s are cached, by the time
_ComponentIdResolver_ gets to it, it will use the cached id, rather than
looking it up at the wrong time. Non-nested tables simply don't get around to
calling _getClientId()_ on their components before _ComponentIdResolver_ runs,
which is probably the real problem.
Could it be an issue with the way _UIDataAdapter.saveChildState(FacesContext
facesContext)_ is written? Note that a nested table would save the state of its
facets in _saveChildState(FacesContext facesContext, UIComponent component)_,
which would result in calls to _getClientId()_ on the facet cells. A top level
table would not save the state of the facets though, b/c we only traverse the
children of the table inside _UIDataAdapter.saveChildState(FacesContext
facesContext)_
was:
Please consider the following test code:
{code}
<rich:dataTable id="testTable"
value="#{dataTableTestBackingBean.rowsModel}"
var="rowVar">
<f:facet name="header">
<rich:column>
<h:outputText value="Column 1" />
</rich:column>
</f:facet>
<rich:column>
<h:inputText id="valTest" value="#{rowVar.col1}" >
<a4j:ajax
event="blur"
render="testColumn, footerTest"
limitRender="true"
execute="@this" />
</h:inputText>
</rich:column>
<rich:column>
<h:outputText id="testColumn"
value="#{dataTableTestBackingBean.footerValue}" />
</rich:column>
<f:facet name="footer">
<rich:column>
<h:outputText id="footerTest"
value="#{dataTableTestBackingBean.footerValue}" />
</rich:column>
</f:facet>
</rich:dataTable>
{code}
This example will fail with the following Javascript error in the browser:
{color:red}
{quote}
Error: During update: formId:testTable:0:footerTest not found
{quote}
{color}
This is expected, b/c the correct id for the footer is
_formId:testTable:footerTest_.
The bug is in _org.richfaces.context.ComponentIdResolver_. Here is what happens:
# The _RenderComponentCallback_ is executed on the input component (_'valTest'_
in the example) and it reads the list of short ids to render from the attached
Ajax Behavior. Note that we got here by walking the parent data table model, so
the current rowKey is 0
# _RenderComponentCallback_ asks _ComponentIdResolver_ to resolve short ids
into client IDs
# _ComponentIdResolver_ starts ascending up the tree from _'valTest'_ and
looking at facets and children until it finds _'footerTest'_.
# At this point it asks for the clientId of _'footerTest'_ w/o regard for the
fact that the data model has a rowKey that is set 0
So, we get the wrong id b/c we call UiData.getClientId() outside of the normal
walking order of that model.
*EDIT:*
I noticed that if I nest the above data table in another data iterator, then
the footer update suddenly starts working. I investigated and it turned out
that nested table will have _getClientId()_ called on all of its components by
the parent table, and since _clientId_ s are cached, by the time
_ComponentIdResolver_ gets to it, it will use the cached id, rather than
looking it up at the wrong time. Non-nested tables simply don't get around to
calling _getClientId()_ on their components before _ComponentIdResolver_ runs,
which is probably the real problem.
> ComponentIdResolver does not resolve clientId correctly
> -------------------------------------------------------
>
> Key: RF-11134
> URL: https://issues.jboss.org/browse/RF-11134
> Project: RichFaces
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Affects Versions: 4.0.0.Final
> Reporter: Val Blant
>
> Please consider the following test code:
> {code}
> <rich:dataTable id="testTable"
> value="#{dataTableTestBackingBean.rowsModel}"
> var="rowVar">
>
> <f:facet name="header">
> <rich:column>
> <h:outputText value="Column 1" />
> </rich:column>
> </f:facet>
>
> <rich:column>
> <h:inputText id="valTest" value="#{rowVar.col1}" >
> <a4j:ajax
> event="blur"
> render="testColumn, footerTest"
> limitRender="true"
> execute="@this" />
> </h:inputText>
> </rich:column>
> <rich:column>
> <h:outputText id="testColumn"
> value="#{dataTableTestBackingBean.footerValue}" />
> </rich:column>
> <f:facet name="footer">
> <rich:column>
> <h:outputText id="footerTest"
> value="#{dataTableTestBackingBean.footerValue}" />
> </rich:column>
> </f:facet>
> </rich:dataTable>
> {code}
> This example will fail with the following Javascript error in the browser:
> {color:red}
> {quote}
> Error: During update: formId:testTable:0:footerTest not found
> {quote}
> {color}
> This is expected, b/c the correct id for the footer is
> _formId:testTable:footerTest_.
> The bug is in _org.richfaces.context.ComponentIdResolver_. Here is what
> happens:
> # The _RenderComponentCallback_ is executed on the input component
> (_'valTest'_ in the example) and it reads the list of short ids to render
> from the attached Ajax Behavior. Note that we got here by walking the parent
> data table model, so the current rowKey is 0
> # _RenderComponentCallback_ asks _ComponentIdResolver_ to resolve short ids
> into client IDs
> # _ComponentIdResolver_ starts ascending up the tree from _'valTest'_ and
> looking at facets and children until it finds _'footerTest'_.
> # At this point it asks for the clientId of _'footerTest'_ w/o regard for the
> fact that the data model has a rowKey that is set 0
> So, we get the wrong id b/c we call UiData.getClientId() outside of the
> normal walking order of that model.
> *EDIT:*
> I noticed that if I nest the above data table in another data iterator, then
> the footer update suddenly starts working. I investigated and it turned out
> that nested table will have _getClientId()_ called on all of its components
> by the parent table, and since _clientId_ s are cached, by the time
> _ComponentIdResolver_ gets to it, it will use the cached id, rather than
> looking it up at the wrong time. Non-nested tables simply don't get around to
> calling _getClientId()_ on their components before _ComponentIdResolver_
> runs, which is probably the real problem.
> Could it be an issue with the way _UIDataAdapter.saveChildState(FacesContext
> facesContext)_ is written? Note that a nested table would save the state of
> its facets in _saveChildState(FacesContext facesContext, UIComponent
> component)_, which would result in calls to _getClientId()_ on the facet
> cells. A top level table would not save the state of the facets though, b/c
> we only traverse the children of the table inside
> _UIDataAdapter.saveChildState(FacesContext facesContext)_
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
_______________________________________________
richfaces-issues mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/richfaces-issues