Hi Mike Thanks for the help. The comments there are very helpful. Specially these comments:
MK >> ".. One of the things I notice is that the key to the row state Map is MK >> the clientid of the dataTable, which of course varies based on the row MK >> index. Is there some reason why the key isn't the row index? ... There is not any special reason. As long as it can be an unique identifier per row, we can use anything. I checked all the code in UIData and there are no side effects that this change could cause. Just for keep in mind, the relevant points are: - setRowIndex() - processDecodes(), processValidators(), processUpdates() - Ajax processPartialExecute() and processPartialRendering() - invokeOnComponent() - visitTree() MK >> What about the possibility of storing the row data in the map using a MK >> key based on the row data itself? That way, changing the row model MK >> (adding/deleting rows) would automatically pick the right row state? It is a viable alternative. By default use the rowIndex but if some option is active use that proposed key. The only case this value could be different is if we handle a Map, but in this case we don't need to worry about that because it just can't handle such structure. To do that, we need to override the code that assume the rowIndex should be attached to the dataTable client id (see HtmlDataTableHack.getContainerClientId()). MK >> The only issues are that we might be keeping the row state for rows MK >> that no longer in the model, and we might be holding onto a reference MK >> to an object that should be garbage collected (I've never delved into MK >> this, but my understanding is that there are ways around referencing MK >> things that should perhaps be garbage-collected). Really that is not a big issue after all, because with JSF 2.0 partial state saving and some other improvements on MyFaces, the state size is very small per row. But anyway we could add a method to remove the state of a row based on a rowKey or identifier. MK >> However, if it works, it would automaticallly solve all of the row MK >> issues transparently to the end-user. Sorting, inserting, deleting MK >> rows would work transparently. Of course. That would be nice!. In resume, we need some interface that do the following points: 1. From a rowIndex retrieve/save the state of a row based on a unique identifier per row (let's call it rowKey). 2. Use a "derivation" of the rowKey and use it on the dataTable container clientId, (let's call it rowKey' ). In that way, values or actions decoded will be handled correctly and will apply to the expected data. If the row is removed. 3. (Optional) Add a method that retrieve a rowIndex based on a rowKey and a method that could convert a rowKey' into a rowKey. The implementation really does not require such methods, but those ones are convenient ones if the user requires some manipulation or remove the state of unused rows. Note we can use in (1) as key rowKey' or another derivation, instead rowKey. I'll investigate more about it and generate a solution based on the previous ideas. regards, Leonardo Uribe 2011/3/14 Mike Kienenberger <[email protected]>: > Leonardo, > > This sounds similar to something I started to investigate four years ago. > > http://mail-archives.apache.org/mod_mbox/myfaces-dev/200704.mbox/%[email protected]%3E > > Maybe you could read through the thread and see if there's anything > useful in there for you. > I was pulled off my JSF project for a couple of years right afterward, > so I never got back to it. > > > On Mon, Mar 14, 2011 at 3:47 PM, Leonardo Uribe (JIRA) > <[email protected]> wrote: >> >> [ >> https://issues.apache.org/jira/browse/TOMAHAWK-1552?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13006593#comment-13006593 >> ] >> >> Leonardo Uribe commented on TOMAHAWK-1552: >> ------------------------------------------ >> >> I committed a solution for t:dataTable. The idea is follow the same idea we >> did >> for detailStamp facet: use a "virtual" component and add it as a facet, with >> a >> renderer that can render the detailStamp content individually. >> >> In this case we created a facet with name "row" and a virtual component with >> id="row". The effect is it is possible to reference each row with a clientId >> and that means we can render the row using the standard tag f:ajax. >> >> If multiple rows are required to be updated, you can always add the >> additional >> rows with a code like this: >> >> datatable.setRowIndex(targetRowIndex); >> PartialViewContext pvc = FacesContext.getCurrentInstance(). >> getPartialViewContext(); >> if (!pvc.isRenderAll()) >> { >> Collection rows = pvc.getRenderIds(); >> String idToAdd = datatable.getFacet("row").getClientId(); >> if (!rows.contains(idToAdd)) >> { >> rows.add(idToAdd); >> } >> } >> >> The advantage is this code relies on the standard ajax mechanism. >> >> I reviewed Richfaces and Trinidad to see how they solve the problem. It is >> clear there is an association between the rowIndex and a rowKey, so to solve >> this both of them has an extended DataModel to deal with this logic. For >> example, in trinidad case there is an interface called >> org.apache.myfaces.trinidad.model.RowKeyIndex . >> >> In theory, there is an old known problem in UIData (since JSF 1.0). >> The interface javax.faces.model.DataModel looks like this: >> >> public abstract class DataModel<E> implements Iterable<E>{ >> public void addDataModelListener(DataModelListener listener); >> public DataModelListener[] getDataModelListeners(); >> public void removeDataModelListener(DataModelListener listener); >> >> //size and ordering >> abstract public int getRowCount(); >> abstract public int getRowIndex(); >> abstract public void setRowIndex(int rowIndex); >> >> abstract public boolean isRowAvailable(); >> public Iterator<E> iterator(); >> >> //row data >> abstract public E getRowData(); >> >> //structure behind model >> abstract public Object getWrappedData(); >> abstract public void setWrappedData(Object data); >> } >> >> In practice, the problem is the model can change between requests, so the >> rowCount/rowIndex changes too, and that causes the row state becomes >> inconsistent on the component side. In tomahawk there exist a solution using >> preserveDataModel attribute. But other possible alternative is make >> t:dataTable or the custom component extending UIData take into consideration >> this fact. How? I don't know yet. I'm still thinking about how to do it. >> In theory for an specific row, the component state of that row must be >> bound in some way to the state using a rowKey. In practice, that rowKey is >> usually some property of the rowData, so the clientId of each component in a >> row must reflect this fact, so when an action or input value is decoded, >> the right state can be loaded and saved. >> >> Now, going back to the initial problem, it is not possible for the moment >> to do something similar to RichFaces ajaxKeys because there is not an >> alternative solution for the previous problem yet. So, the best we can do >> for now is provide the previous solution, but I'll continue investigating >> what can we do in this case. >> >> >>> t:dataList, t:dataTable ajax >>> ---------------------------- >>> >>> Key: TOMAHAWK-1552 >>> URL: https://issues.apache.org/jira/browse/TOMAHAWK-1552 >>> Project: MyFaces Tomahawk >>> Issue Type: New Feature >>> Components: Data List >>> Environment: ALL >>> Reporter: Dave >>> >>> dataList and dataTable: allow ajax reRender specified rows. Richfaces uses >>> ajaxKeys to specified row indice to be reRendered for ajax request. >> >> -- >> This message is automatically generated by JIRA. >> For more information on JIRA, see: http://www.atlassian.com/software/jira >> >
