GWT CellTable SelectionModel can not deselect item after editing - gwt

Hello I have a Contact class with informations which i show in a CellTable.
The CellTable has a DataListProvider, MultiSelectionModel and KeyProvider
which checks the id of the Contact.
DataListProvider and CellTable have the same KeyProvider.
if i only select/deselect the items in the CellTable and show them in a TextBox ists working fine. But the when i change the value of the Contact item in the TextBox(Contact instance) and try to deselect the item the selectionmodel says its still selected?
I tried with clear() but its still selected!
GWT 2.5 / FireFox
ProvidesKey<Contact> keyProvider = new ProvidesKey<Contact>(){
#Override
public Object getKey(Contact item) {
return item.getIdContact();
}
};
public MyCellTable(boolean canLoad, Integer pagesize, ProvidesKey<T> keyProvider) {
super(-1, resource, keyProvider);
selectionModel = new MultiSelectionModel<T>();
selectionModel .addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
selectionChange();
}
});
dataProvider = new ListDataProvider<T>(keyProvider);
dataProvider.addDataDisplay(this);
}
in the selection event i call
protected void selectionChange(){
Contact c = grid.getGrid().getSelectedItem();
if(c != null){
cpForm.enable();
cpForm.clear();
form.bind(c); // Formular which updates the selected instance
cpForm.add(form);
}else{
cpForm.disable(noseletionText);
}
}
i have no ValueUpdater
when i select an item i generate a formular and if i change something i call:
#Override
public void save() {
super.save();
ContactServiceStore.get().updateContact(manager.getBean(),
new MyAsyncCallback<Void>() {
#Override
public void onSuccess(Void result) {
onchange();
}
});
}
i if call the method without changes on the contact its still working and i can deselect but when i change the name or something else i cant select other items or deselect the current item!

You're not actually using your ProvidesKeys in your MultiSelectionModel. You need to create your MultiSelectionModel like so:
MultiSelectionModel<T> selectionModel = new MultiSelectionModel<T>(keyProvider);
If you don't supply the MultiSelectionModel with a ProvidesKey it will use the actual object as a key.
Make sure you also add the MultiSelectionModel to the table:
cellTable.setSelectionModel(selectionModel);
The reason selectionModel.clear() wasn't working was because selectionModel was not set to the table.

Related

Delete rows from Nattable

I want to implement a row deletion logic in a Nebula Nattable.
This is what I plan to do:
Add context menu to the Nattable which is described in http://blog.vogella.com/2015/02/03/nattable-context-menus-with-eclipse-menus/
Add an SWT Action to the menu which will implement the delete
my question is, which is the best way to accomplish this:
Should I delete the corresponding value from my data model and the table view is refreshed when I execute this.natview.refresh();?
OR
Should I get the rows from SelectionLayer and delete them (if so how do I do ?)?
OR
is there any default support for this function through IConfiguration?
In NatTable you would typically do the following:
Create a command for deleting a row
public class DeleteRowCommand extends AbstractRowCommand {
public DeleteRowCommand(ILayer layer, int rowPosition) {
super(layer, rowPosition);
}
protected DeleteRowCommand(DeleteRowCommand command) {
super(command);
}
#Override
public ILayerCommand cloneCommand() {
return new DeleteRowCommand(this);
}
}
Create a command handler for that command
public class DeleteRowCommandHandler<T> implements ILayerCommandHandler<DeleteRowCommand> {
private List<T> bodyData;
public DeleteRowCommandHandler(List<T> bodyData) {
this.bodyData = bodyData;
}
#Override
public Class<DeleteRowCommand> getCommandClass() {
return DeleteRowCommand.class;
}
#Override
public boolean doCommand(ILayer targetLayer, DeleteRowCommand command) {
//convert the transported position to the target layer
if (command.convertToTargetLayer(targetLayer)) {
//remove the element
this.bodyData.remove(command.getRowPosition());
//fire the event to refresh
targetLayer.fireLayerEvent(new RowDeleteEvent(targetLayer, command.getRowPosition()));
return true;
}
return false;
}
}
Register the command handler to the body DataLayer
bodyDataLayer.registerCommandHandler(
new DeleteRowCommandHandler<your type>(bodyDataProvider.getList()));
Add a menu item to your menu configuration that fires the command
new PopupMenuBuilder(natTable)
.withMenuItemProvider(new IMenuItemProvider() {
#Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem deleteRow = new MenuItem(popupMenu, SWT.PUSH);
deleteRow.setText("Delete");
deleteRow.setEnabled(true);
deleteRow.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
natTable.doCommand(new DeleteRowCommand(natTable, rowPosition));
}
});
}
})
.build();
Using this you don't need to call NatTable#refresh() because the command handler fires a RowDeleteEvent. I also don't suggest to call NatTable#refresh() in such a case, as it might change and refresh more than it should and would not update other states correctly, which is done correctly by firing the RowDeleteEvent.
Note that the shown example deletes the row for which the context menu is opened. If all selected rows should be deleted, you should create a command handler that knows the SelectionLayer and retrieve the selected rows as shown in the other answer.
In our application we do the following:
Get selected row objects:
SelectionLayer selectionLayer = body.getSelectionLayer();
int[] selectedRowPositions = selectionLayer.getFullySelectedRowPositions();
Vector<Your Model Objects> rowObjectsToRemove = new Vector<Your Model Objects>();
for (int rowPosition : selectedRowPositions) {
int rowIndex = selectionLayer.getRowIndexByPosition(rowPosition);
rowObjectsToRemove .add(listDataProvider.getRowObject(rowIndex));
}
Remove them from the data provider
call natTable.refresh()

What is the right usage for the SingleSelectionModel?

we would like to link from a CellTable to a property editor page. We use the SingleSelectionModel to get notified, when a user clicks on an item.
It is initialized like this:
private final SingleSelectionModel<Device> selectionModel = new SingleSelectionModel<Device>();
We then assign the selection change handler:
selectionModel.addSelectionChangeHandler(this);
Our selection change handler looks like this:
#Override
public void onSelectionChange(SelectionChangeEvent event) {
Log.debug("DevicesPresenter: SelectionChangeEvent caught.");
Device selectedDevice = selectionModel.getSelectedObject();
if (selectedDevice != null) {
selectionModel.clear();
if (selectionModel.getSelectedObject() != null){
Log.debug("DevicesPresenter: selected item is " + selectionModel.getSelectedObject());
}
else{
Log.debug("DevicesPresenter: selected item is null");
}
deviceEditorDialog.setCurrentDevice(selectedDevice.getUuid());
// get the container data for this device
clientModelProvider.fetchContainersForDevice(selectedDevice.getUuid());
PlaceRequest request = new PlaceRequest.Builder()
.nameToken(NameTokens.deviceInfo)
.with("uuid", selectedDevice.getUuid())
.build();
Log.debug("Navigating to " + request.toString());
placeManager.revealPlace(request);
}
}
Now there are two issues: There always seem to be two SelectionChangeEvents at once and i really cannot see why. The other thing is: How is the right way do handle selection of items and the related clearing of the selection model? Do we do that the right way?
Thanks!
If you only want to get notified of "clicks" without keeping the "clicked" item selected, use a NoSelectionModel instead; no need to clear the selection model as soon as something is selected.
As for your other issue with being called twice, double-check that you haven't added your selection handler twice (if you can unit-test your DevicesPresenter, introspect the handlers inside the selection model for example)
In your line selectionModel.addSelectionChangeHandler(this); what does this refer?
Here my code how I use SingleSelectionModel
public class MyClass{
private final SingleSelectionModel<CountryDto> selectionModel = new SingleSelectionModel<CountryDto>();
...
public MyClass(){
cellTable.setSelectionModel(selectionModel);
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
CountryDto selected = selectionModel
.getSelectedObject();
if (selected != null) {
Window.alert("Selected country "+selected.getTitle());
}
}
});
}
}

GWT Header checkbox to check / uncheck all checkboxes in my table

I´ve created an CellTable with the Google Web Toolkit.
I just started using it and my knowledge about it is very small...
However I was searching for a tutorial or just a code example of how to create a checkbox in the CellTable header but everythin I´ve found I didn´t understand or it didn´t worked.
So far I´ve got this code to create a Column for checkboxes and a normal table mostly the same as the Google tutorial for a CellTable:
Column<Contact, Boolean> checkColumn = new Column<Contact, Boolean>(
new CheckboxCell(true, false)) {
#Override
public Boolean getValue(Contact contact) {
return null;
}
};
table.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
table.setColumnWidth(checkColumn, 40, Unit.PX);
Now I´m searching for the code to add a checkbox to the header and how to make it check or uncheck all checkboxes.
Thanks for your time.
From my blog post:
Here is a simple column header that selects/ de-selects all rows in a table. When all rows are checked, the header becomes checked automatically. Clicking the checkbox in the header causes either to select or de-select all rows.
I am using the selection model and the data list provider to do the selection magic. It may not work for everyone.
And here is my custom header:
public final class CheckboxHeader extends Header {
private final MultiSelectionModel selectionModel;
private final ListDataProvider provider;
public CheckboxHeader(MultiSelectionModel selectionModel,
ListDataProvider provider) {
super(new CheckboxCell());
this.selectionModel = selectionModel;
this.provider = provider;
}
#Override
public Boolean getValue() {
boolean allItemsSelected = selectionModel.getSelectedSet().size() == provider
.getList().size();
return allItemsSelected;
}
#Override
public void onBrowserEvent(Context context, Element elem, NativeEvent event) {
InputElement input = elem.getFirstChild().cast();
Boolean isChecked = input.isChecked();
for (TYPE element : provider.getList()) {
selectionModel.setSelected(element, isChecked);
}
}
}
See http://code.google.com/p/google-web-toolkit/issues/detail?id=7014

How to add a Clickhandler to a cellTable cell (or row )

I would like to have a handler on a column of my cellTable.The column is an ImageResourceCell and I would that when I click on it, it delete the row
Here is my code
Column<MyObject, ImageResource> imageColumn =
new Column<MyObject, ImageResource>(newImageResourceCell()) {
#Override
public ImageResource getValue(MyObject object) {
return Bundle.Util.getInstance().deleteRegexButton();
}
};
cellTable.addColumn(imageColumn,SafeHtmlUtils.fromSafeConstant("<br/>");
But I didn't know how to insert a handler as described
Is it possible ??
any suggestions are welcome
Thanks.
Cells have to declare the events they handle, then the browser event can be passed to the cell.
ImageResourceCell myImgCell = new ImageResourceCell() {
public Set<String> getConsumedEvents() {
HashSet<String> events = new HashSet<String>();
events.add("click");
return events;
}
};
Column<MyObject, ImageResource> imageColumn = new Column<MyObject, ImageResource>(myImgCell) {
#Override
public ImageResource getValue(MyObject dataObj) {
return Bundle.Util.getInstance().deleteRegexButton();
}
#Override
public void onBrowserEvent(Context context, Element elem,
MyObject object, NativeEvent event) {
super.onBrowserEvent(context, elem, object, event);
if ("click".equals(event.getType())) {
//call your click event handler here
}
}
};
More info here: http://code.google.com/webtoolkit/doc/latest/DevGuideUiCustomCells.html
Note: this works with GWT 2.4, did not try with GWT 2.2.
Have you seen Adding clickHandler to row in CellTable in GWT??
A CellTable has built in support for handling click events. You can add a CellPreviewHandler that will be called among others when a row is clicked. It will receive a number of items in the event like the native event, cell, and data row value. Because it fires not only for click events you need to check if the click event was fired. Simply test the event passed:
boolean isClick = "click".equals(event.getNativeEvent().getType())

Setting ListGrid selection in SmartGWT

I'm trying to set the selected records of a ListGrid table object in SmartGWT, but I can't find any way of doing it. I know there's a getSelectedRecords() function, but no matching setSelectedRecords(). I tried to see if set/getSelectedState() would work, but GWT complains about needing a primary key and a DataSource object. Is there any way to set the selection of a ListGrid?
For this you can use one of the selectRecords() methods, like so:
public void onModuleLoad()
{
VLayout main = new VLayout();
final ListGrid grid = new ListGrid();
grid.setHeight(500);
grid.setWidth(400);
grid.setFields(new ListGridField("name", "Name"));
grid.setData(createRecords());
final IButton button = new IButton("Select some");
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event)
{
grid.selectRecords(new int[]{2, 3}); //This will select index 2 and 3
}
});
main.addMember(grid);
main.addMember(button);
RootPanel.get().add(main);
}
private ListGridRecord[] createRecords()
{
return new ListGridRecord[]{
createRecord("monkey"),
createRecord("banana"),
createRecord("orange"),
createRecord("sun")
};
}
private ListGridRecord createRecord(String name)
{
ListGridRecord record = new ListGridRecord();
record.setAttribute("name", name);
return record;
}