[
https://issues.apache.org/jira/browse/MYFACES-2616?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Leonardo Uribe resolved MYFACES-2616.
-------------------------------------
Resolution: Fixed
> Fix UIData state saving model (spec issue 153)
> ----------------------------------------------
>
> Key: MYFACES-2616
> URL: https://issues.apache.org/jira/browse/MYFACES-2616
> Project: MyFaces Core
> Issue Type: Task
> Components: JSR-314
> Affects Versions: 2.0.0-beta-2
> Reporter: Leonardo Uribe
> Assignee: Leonardo Uribe
> Fix For: 2.1.0
>
> Attachments: UIDataPreserveRowComponentStateTest.java,
> fixUIDataPSS-6.patch, fixUIDataPSS-7.patch, fixUIDataPSS-8.patch,
> fixUIDataPSS-9-3-2.patch, fixUIDataPSS-9-3-no-markInitialStateFix-3.patch,
> myfaces-uidata-component-state-test.zip
>
>
> In short, this topic is an attempt to add full state to components inside
> UIData. I'll do a brief resume, so people can understand this one easily.
> UIData uses the same component instances to render multiple rows. Suppose
> this example:
> <h:dataTable id="cities" var="city" value="#{country.cities}">
> <h:column>
> <h:outputText value="#{city}" />
> </h:column>
> </h:dataTable>
> In the component tree it is created this hierarchy:
> HtmlDatatable
> UIColumn
> HtmlOutputText
>
> If we have 10 cities, the same component is used over and over to render all
> 10 cities. The reason to do that in this way is keep state as small as
> possible.
> Now let's suppose something like this:
> <h:dataTable id="cities" var="city" value="#{country.cities}">
> <h:column>
> <h:inputText value="#{city}" />
> </h:column>
> </h:dataTable>
> It was changed the output component for an input one. If this table is in a
> form and the values are submitted, the same component is used to apply
> request values, validate and apply them to the model (update process). To
> make this possible, UIData class has some code to preserve this values
> between phases (using EditableValueHolder interface), so when each phase is
> processed, all rows are traversed and you get the expected behavior.
> Now suppose something more complex: We have a code that use invokeOnComponent
> to change the style of my inputText. In theory, only one row should change.
> But in fact, all rows are rendered with the same color. Why? because we use
> the same component to render all rows, and we don't preserve the children
> component state between rows.
> There is a lot of issues, questions, and side effects related to this issue,
> but just to put some of them here:
> TOMAHAWK-1062 InputTextArea doesn't work properly inside facet DetailStamp
> TOMAHAWK-96 Data table Scroller not working the dataTable which was actually
> contained in other DataTable
> https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=153
> Problems with UIData state saving
> Also, it is well know that one reason why people uses c:forEach in facelets,
> is because this one create "full" components per each row. It is very easy to
> find articles on internet.
> Now, with jsf 2.0 we have partial state saving, so we have a chance to fix
> this one once and for all. I tried fix this one per months (maybe years!),
> but talking with Martin Marinschek on JSFDays, some ideas came out and
> finally it was found a possibility to fix this one using the existing api and
> with little changes on the spec.
> The proposal is this:
> 1. Do not call UIComponent.markInitialState() on ComponentTagHandlerDelegate,
> as ComponentHandler javadoc says, instead call it after PostAddToViewEvent
> are published on vdl.buildView(). We need to call it from root to nodes, so
> the parent component is marked first. I know the place where this call comes
> is from trinidad tag handler, but this call needs to be fixed in a more
> predictable way.
> 2. Use an attribute on facesContext to identify when the VDL is marking the
> initial state (in myfaces there is already an attribute called
> "org.apache.myfaces.MARK_INITIAL_STATE"). This is necessary to indicate
> UIData instances that it is time to save the full state of all component
> children,
> 3. Allow UIData to hold a map where the key are client ids and the value are
> the deltas of all components per row. This map should be saved and restored.
> 4. Change UIData.setRowIndex() to restore and save the component state.
> I'll attach a patch on this issue with the algorithm proposed (because it is
> based on myfaces codebase). It was tested and it works. But note it is
> necessary to fix the javadoc for UIData.markInitialState(), ComponentHandler
> and maybe vdl.buildView(), so the intention is propose this change for jsf
> 2.0 rev A. Note this works only with PSS enabled because without it we don't
> have a place to notify UIData instances that it is necessary to get the full
> state. Also, note this patch preserve backward compatibility, because the old
> way to store/save is applied after the full state is restored.
> Really, I have the strong temptation to apply some similar code on myfaces
> UIRepeat component (because this class is private), but I prefer first ask to
> EG.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira