开发者

GWT SelectionModel is returning old selection

开发者 https://www.devze.com 2023-04-08 19:06 出处:网络
I have a cell table with an async data provider. If I update the data via the data provider the table renders the new data correctly but the selection 开发者_如何学JAVAmodel still holds onto and retur

I have a cell table with an async data provider. If I update the data via the data provider the table renders the new data correctly but the selection 开发者_如何学JAVAmodel still holds onto and returns old objects.

Any ideas how to refresh the selection model?


I think you should make your SelectionModel work with different instance of the same "logical" object using the appropriate ProvidesKey. For instance, you could use ProvidesKey that calls getId on the object, so that two objects with the same such ID would be considered equal; so even if the SelectionModel holds onto the old object, it can still answer "yes, it's selected" when you give it the new object.
FYI, this is exactly what the EntityProxyKeyProvider does (using the stableId of the proxy). And the SimpleKeyProvider, used by default when you don't specify one, uses the object itself as its key.


I came across the same issue. Currently I have this as single selection model.

SelectedRow = store it when you select it.

Then when data is reloaded you can clear it by

celltable.getSelectionModel().setSelected(SelectedRow, false);

I guess it is too late for you but hope it helps someone else.


Here is my manual method for refreshing the SelectionModel. This allows you to use the selectedSet() when needed and it will actually contain the current data, rather than the old data - including the removal of deleted rows and updated fields!

I have included bits & pieces of a class extending DataGrid. This should have all the logic at least to solve your problems.

  1. When a row is selected, call saveSelectionKeys().

  2. When the grid data is altered call refeshSelectedSet().

  3. If you know the key type, you can replace the isSameKey() method with something easier to deal with. This class uses generics, so this method attempts to figure out the object conversion itself.

.

public abstract class AsyncDataGrid<T> extends DataGrid<T> {
    ...

    private MultiSelectionModel<T> selectionModel_; 
    private ListDataProvider<T> dataProvider_;
    private List<T> dataList_;      
    private Set<Object> priorSelectionKeySet_;
    private boolean canCompareKeys_;
    ...

    public AsyncDataGrid( final ProvidesKey<T> keyProvider ){
        super( keyProvider );

        ...

        dataProvider_ = new ListDataProvider<T>();         
        dataList_ = dataProvider_.getList();            
        canCompareKeys_ = true;
        ...
    }   

    private void saveSelectionKeys(){
        priorSelectionKeySet_ = new HashSet<Object>();
        Set<T> selectedSet = selectionModel_.getSelectedSet();
        for( Iterator<T> it = selectedSet.iterator(); it.hasNext(); ) {
            priorSelectionKeySet_.add( super.getValueKey( it.next() ) );
        }
    }

    private void refeshSelectedSet(){
        selectionModel_.clear();
        if( priorSelectionKeySet_ != null ){
            if( !canCompareKeys_ ) return; 
            for( Iterator<Object> keyIt = priorSelectionKeySet_.iterator(); keyIt.hasNext(); ) {            
                Object priorKey = keyIt.next();         
                for( Iterator<T> it = dataList_.iterator(); it.hasNext(); ) {
                    T row = it.next();
                    Object rowKey = super.getValueKey( row );
                    if( isSameKey( rowKey, priorKey ) ) selectionModel_.setSelected( row, true );
                }
            }       
        }
    }

    private boolean isSameRowKey( final T row1, final T row2 ) {
        if( (row1 == null) || (row2 == null) ) return false;
        Object key1 = super.getValueKey( row1 );
        Object key2 = super.getValueKey( row2 );
        return isSameKey( key1, key2 );
    }   

    private boolean isSameKey( final Object key1, final Object key2 ){  
        if( (key1 == null) || (key1 == null) ) return false;        
        if(      key1 instanceof Integer ){
            return ( ((Integer) key1) - ((Integer) key2) == 0 );            
        }
        else if( key1 instanceof Long ){
            return ( ((Long) key1) - ((Long) key2) == 0 );          
        }
        else if( key1 instanceof String ){
            return ( ((String) key1).equals( ((String) key2) ) );           
        }       
        canCompareKeys_ = false;
        return false;
    }
}


I fixed my particular issue by using the following code to return the visible selection. It uses the selection model to determine what is selected and combines this with what is visible. The objects themselves are returned from the CellTable data which is always upto date if the data has ever been changed via an async provider (the selection model data maybe stale but the keys will be correct)

public Set<T> getVisibleSelection() {

    /*
     * 1) the selection model contains selection that can span multiple pages -
     * we want to return just the visible selection
     * 2) return the object from the cellTable and NOT the selection - the
     * selection may have old, stale, objects if the data has been updated
     * since the selection was made
     */
    Set<Object> selectedSet = getKeys(selectionModel.getSelectedSet());
    List<T> visibleSet = cellTable.getVisibleItems();
    Set<T> visibleSelectionSet = new HashSet<T>();
    for (T visible : visibleSet) {
        if (selectedSet.contains(KEY_PROVIDER.getKey(visible))) {
            visibleSelectionSet.add(visible);
        }
    }

    return visibleSelectionSet;
}

public static Set<Object> getKeys(Collection<T> objects) {

    Set<Object> ids = new HashSet<Object>();
    for (T object : objects) {
        ids.add(KEY_PROVIDER.getKey(object));
    }
    return ids;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号