SelectionModel and ListDataProvider are out of synch

54 views
Skip to first unread message

Mirco Dotta

unread,
Nov 5, 2010, 6:48:40 AM11/5/10
to Google Web Toolkit
Hi guys,

I'm experiencing an annoying problem with my SelectionModel beeing out
of synch in respect of the data stored in my ListDataProvider. Maybe
I'm doing something wrong, but I guess there is a suddle bug that
prevents to correctly update the selection model when the data in the
ListDataProvider change.

Below, I pasted a contrived working example that you can test to
expose the blamed behavior. Basically, you start with a table that
contains two rows. Then you add a new row (click the add button) and
you should see the "baz" row. Now select it and click remove.
Everything is fine, good. Do it once more: add a row and delete it
and... you get an expection, that is because of the assertion I've
introduce in the remove button click handler. Check the code and the
assertion is there only to expose the fact that the SelectionModel has
more than one eIement in the set... it actually holds two elements,
the currently selected row (which is good) and the one that was
deleted before....aaaargh?! So it looks like the the set of selected
elements hold in the SelectionModel is not in synch with the data hold
by the ListDataProvider, this despite all Foo's objects are different
(look at the FooKeys).

Opinions?

public class TestTable implements EntryPoint {

private static int counter = 0;

class Foo {

int id;
String text;

Foo(String text) {
this.id = ++TestTable.counter;
this.text = text;
}
}

class FooKeys implements ProvidesKey<Foo> {
@Override
public Object getKey(Foo item) {
return item.id;
}
}

private final List<Foo> backend = new ArrayList<Foo>();

public void onModuleLoad() {
backend.add(new Foo("foo"));
backend.add(new Foo("bar"));

ProvidesKey<Foo> keys = new FooKeys();
final ListDataProvider<Foo> dataProvider = new
ListDataProvider<Foo>(keys);
final CellTable<Foo> table = new CellTable<Foo>(15, keys);
final MultiSelectionModel<Foo> selectionModel = new
MultiSelectionModel<Foo>(keys);
table.setSelectionModel(selectionModel);
dataProvider.addDataDisplay(table);

table.addColumn(new TextColumn<Foo>() {

@Override
public String getValue(Foo object) {
return object.text;
}
});
FlowPanel panel = new FlowPanel();
panel.add(table);

Button add = new Button("Add");
add.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Foo e = new Foo("baz");
List<Foo> res = new ArrayList<Foo>(backend);
res.add(e);
dataProvider.setList(res);
}
});

panel.add(add);

Button remove = new Button("Remove");
remove.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Set<Foo> els = selectionModel.getSelectedSet();
Foo foo = (Foo) els.toArray()[0];
assert (els.size() == 1); // this fails!
dataProvider.setList(backend);
}
});

panel.add(remove);

RootPanel.get().add(panel);

dataProvider.setList(new ArrayList<Foo>(backend));
}
}

-- Mirco

John LaBanca

unread,
Nov 5, 2010, 8:56:06 AM11/5/10
to google-we...@googlegroups.com
The SelectionModel shouldn't depend on the data in the ListDataProvider because it is independent of the data source.  Consider a SelectionModel that has an option to select all unread messages.  You probably don't have all of the user messages loaded on the client, but the unread messages should be selected as you page through the table, without having to update the SelectionModel each time you load a new page.  Also, SelectionModels can be shared across multiple CellTables, each with its own ListDataProvider.

Can you deselect the value in the SelectionModel when you remove the row in your onClick handler?  

Thanks,
John LaBanca
jlab...@google.com



--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Mirco Dotta

unread,
Nov 7, 2010, 1:42:04 PM11/7/10
to Google Web Toolkit
Hi John,


> The SelectionModel shouldn't depend on the data in the ListDataProvider
> because it is independent of the data source.  Consider a SelectionModel
> that has an option to select all unread messages.  You probably don't have
> all of the user messages loaded on the client, but the unread messages
> should be selected as you page through the table, without having to update
> the SelectionModel each time you load a new page.  

Your point makes sense and I see now why the SelectionModel
has been designed not to be tighted to the data provider. It is about
flexibility
and by having this design, it is easier (and feasible) to integrate a
selection model
when data is loaded asynchronously.

> Can you deselect the value in the SelectionModel when you remove the row in
> your onClick handler?

Yes, this is what I'm currently doing... it is just that, at first
thought, it didn't
feel right. I was believing that removing an item from the data list
should have automagically
removed the item from the selection model. I just thought that the
operation should have been
transparent to API's clients. But I see that data pagination is a hard
problem if you set a hard link
between the selection model and the data provider, which gives me an
explanation of the current
design.

Thank you again for your answer and, please, feel free to correct me
if my comments are wrong (or just
not understandable :).

-- Mirco

Mirco Dotta

unread,
Nov 8, 2010, 3:27:47 AM11/8/10
to Google Web Toolkit
On a related subject why is there no 'reset'/'clear' method on the
selection model.

I find myself in the situation where I would need to reset the
selection model (affecting
a new one is not an option as I have handlers registered on the
former).

Thanks,
Mirco
Reply all
Reply to author
Forward
0 new messages