[ https://issues.apache.org/jira/browse/MYFACES-2616?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12847567#action_12847567 ]
Leonardo Uribe commented on MYFACES-2616: ----------------------------------------- Attached patch with fix for transient properties as suggested by Alexander Smirnov. The idea is create an interface that allows to save/restore transient properties like UIForm.submitted, to be saved per row. In that way, the state could be fully restored and saved for each component. > 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 > Attachments: fixUIDataPSS-6.patch, fixUIDataPSS-7.patch > > > 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. - You can reply to this email to add a comment to the issue online.