I've recently integrated GWT RequestFactory and GXT 3.0 beta. And wrote some extended widgets.Here is my improved DualListField. It has interconnected stores so if you add some values to the right list, they will be removed from the left automatically.
The following algorithm is used to edit existing entity:
1. Populate right list with children from editable entity.
2. Populate left list with async request to the reference on the server.
Code:
package ru.mesotron.jpauc.client.widget.form;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.event.StoreAddEvent;
import com.sencha.gxt.data.shared.event.StoreAddEvent.StoreAddHandler;
import com.sencha.gxt.widget.core.client.ListView;
public class DualListField<M extends EntityProxy, T> extends com.sencha.gxt.widget.core.client.form.DualListField<M, T> {
protected ListStore<M> fromStore;
protected ListStore<M> toStore;
protected ListView<M, T> fromView;
protected ListView<M, T> toView;
@UiConstructor
public DualListField(final ListStore<M> fromStore, final ListStore<M> toStore, ValueProvider<M, T> valueProvider, Cell<T> cell) {
super(fromStore, toStore, valueProvider, cell);
// Inheritance fix
this.fromStore = fromStore;
this.toStore = toStore;
fromView = getFromView();
toView = getToView();
// If 'toStore' receives some item then the item should be removed from 'fromStore'.
toStore.addStoreAddHandler(new StoreAddHandler<M>() {
@Override
public void onAdd(StoreAddEvent<M> event) {
for (M item : event.getItems()) {
M deleteItem = null;
for (M existingItem : fromStore.getAll()) {
if (existingItem.stableId().equals(item.stableId())) {
deleteItem = existingItem;
}
}
if (deleteItem != null) {
fromStore.remove(deleteItem);
}
}
}
});
// If the item already exists in 'toStore' then it shoul be removed from 'fromStore'
fromStore.addStoreAddHandler(new StoreAddHandler<M>() {
@Override
public void onAdd(StoreAddEvent<M> event) {
for (M entity : event.getItems()) {
for (M existing : toStore.getAll()) {
if (existing.stableId().equals(entity.stableId())) {
fromStore.remove(entity);
}
}
}
}
});
}
@Override
protected void onAllLeft() {
List<M> sel = new ArrayList<M>(toStore.getAll());
toStore.clear();
fromStore.addAll(sel);
}
@Override
protected void onAllRight() {
List<M> sel = fromStore.getAll();
toStore.addAll(sel);
}
@Override
protected void onRight() {
List<M> sel = fromView.getSelectionModel().getSelectedItems();
if (sel.size() > 0) {
toStore.addAll(sel);
toView.getSelectionModel().select(sel, false);
}
}
}