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
>>
>

Reply via email to