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

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

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

Create GWT Datagrid with a checkbox column

I have successfully created a datagrid table with two columns. A checkbox col and a string col. When I press a button I want to get the selected strings. Currently when I press the button i get an empty hash set.
Selection Model:
private MultiSelectionModel<String> selectionModel = new MultiSelectionModel<String>(KEY_PROVIDER);
Here is how I create the column
Column<String, Boolean> checkColumn =
new Column<String, Boolean>(new CheckboxCell(true, false)) {
#Override
public Boolean getValue(String object) {
// Get the value from the selection model.
return selectionModel.isSelected(object);
}
};
Here is the method that is called from the button
public Set<String> getSelectedItems(){
Set<String> s = selectionModel.getSelectedSet();
return s;
}
Two pieces are missing. You need to add a FieldUpdater to your checkColumn, and you need to link it to a checkbox manager. Replace T with your Object:
checkColumn.setFieldUpdater(new FieldUpdater<T, Boolean>() {
#Override
public void update(int index, T object, Boolean value) {
getSelectionModel().setSelected(object, value);
dataProvider.refresh();
}
});
setSelectionModel(selectionModel, DefaultSelectionEventManager.<T> createCheckboxManager(0));

GWT Header CheckBox requires two clicks to fire setValue, after changing its value programatically

I have a GWT DataGrid, and a CheckBox in the Header to select/deselect all rows in the grid.
The code for the CheckBox Header is as follows:
private class CheckboxHeader extends Header<Boolean> implements HasValue<Boolean> {
private boolean checked;
private HandlerManager handlerManager;
/**
* An html string representation of a checked input box.
*/
private final SafeHtml INPUT_CHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\" checked/>");
/**
* An html string representation of an unchecked input box.
*/
private final SafeHtml INPUT_UNCHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\"/>");
#Override
public void render(Context context, SafeHtmlBuilder sb) {
if (Boolean.TRUE.equals(this.getValue())) {
sb.append(INPUT_CHECKED);
} else {
sb.append(INPUT_UNCHECKED);
}
};
public CheckboxHeader() {
super(new CheckboxCell(true, false));
checked = true;
}
// This method is invoked to pass the value to the CheckboxCell's render method
#Override
public Boolean getValue() {
return checked;
}
#Override
public void onBrowserEvent(Context context, Element elem, NativeEvent nativeEvent) {
int eventType = Event.as(nativeEvent).getTypeInt();
if (eventType == Event.ONCHANGE) {
nativeEvent.preventDefault();
// use value setter to easily fire change event to handlers
setValue(!checked, true);
}
}
#Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
return ensureHandlerManager().addHandler(ValueChangeEvent.getType(), handler);
}
#Override
public void fireEvent(GwtEvent<?> event) {
ensureHandlerManager().fireEvent(event);
}
#Override
public void setValue(Boolean value) {
setValue(value, true);
}
#Override
public void setValue(Boolean value, boolean fireEvents) {
checked = value;
if (fireEvents) {
ValueChangeEvent.fire(this, value);
}
}
private HandlerManager ensureHandlerManager() {
if (handlerManager == null) {
handlerManager = new HandlerManager(this);
}
return handlerManager;
}
}
So, I add the Header to the grid, and I add a ValueChangeHandler to it to do the actual selecting/deselecting of individual CheckBox cells in every row of the grid. This all works.
Every CheckBoxCell has a Field Updater, and on every update it loops through every item in the grid to see if they are all checked, and update the header check box. If at least one is unchecked, the header checkbox will be unchecked. I call setValue() on the header check box, and after that I call redrawHeaders() on the entire grid. This also works.
What doesn't work is - after changing the "state" of the header check box programatically, it takes two clicks for it to fire it's internal setValue again, and therefore trigger my handler. And what's even funnier - the first click does change the state of the check box, but it just doesn't fire the event.
Any help would be appreciated.
How are you constructing the CheckboxCells themselves? I ran into a similar issue with a column of checkboxes "eating" clicks, and the solution was to call CheckboxCell cell = new CheckboxCell(true,true) and then pass that cell into the constructor of the column.

GWT CellTable SelectionModel can not deselect item after editing

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.

GWT:selection model not working properly

I have a celltable in GWT which have checkboxes, to select multiple checkboxes i am using selectionModel,once I check any checkbox its values get saved in the selectionModel,but then when i uncheck the checkbox , they never get remove , i want to remove the previous selection , how can it be possible
below is the code
List<Categories> selected;
display.getListWidget().getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
selected = new ArrayList<Categories>(
((MultiSelectionModel<Categories>) display.getListWidget().getSelectionModel()).getSelectedSet());
}
});
What i am trying to do is
display.getListWidget().getSelectionModel().setSelected(categories, false);
but its not working , coz i guess categories is not the one which is already added ..
Any Suggestions
Thanks
If you could clarify your question with some more code or by being more specific, we might be able to give a better answer. From your question, I'm guessing that your Categories equals and hashcode are not overwritten in a way that the "categories" you are trying to set is being found.
I'm guessing a bit here but I think a KeyProvider will help you deselect the correct Categories object.
view:
SelectionModel<Categories> selectionModel;
ProvidesKey<Categories> keyProvider = new ProvidesKey<Categories>() {
public Object getKey(Categories categories) {
return item == null ? null : categories.id() // or some unique identifier
}
};
CellTable cellTable = new CellTable<Categories>(keyProvider);
// Omitted..Add columns..
selectionModel = new MultiSelectionModel<Categories>(keyProvider);
cellTable.setSelectionModel(selectionModel);
presenter:
List<Categories> selected;
display.getListWidget().getSelectionMode().addSelectionChangeHandler(
new SelectionChangeHandler() {
public void onSelectionChange() {
MultiSelectionModel selectionModel =
(MultiSelectionModel) display.getListWidget().getSelectionModel();
selected = Lists.newArrayList(selectionModel.getSelectedSet());
}
});