GWT Celtable: two clicks required to change the state of a checkbox in FireFox
In my project, I have a CellTable with a CheckBoxCell column. It is a regular column to represent (change) values ββand is not used for row selection (I use SingleSelectionModel for selection). Everything works fine in Chrome, the first time I clicked it gets the checkbox state and the row is selected. In FireFox, when I try to click on a checkbox in a CheckBoxCell column, GWT selects the row and after the second click on the checkbox changes the state of the checkbox. But I need the same behavior as in Chrome (check the checkbox first).
This is how I create the column:
private <C> Column<T, C> addColumn(CellTable<T> itemListTable, Cell<C> cell, String headerText, int columnWidthPct, final IValueGetter<C, T> getter, @Nullable FieldUpdater<T, C> fieldUpdater) {
Column<T, C> column = new Column<T, C>(cell) {
@Override
public C getValue(T object) {
return getter.getValue(object);
}
};
column.setFieldUpdater(fieldUpdater);
column.setSortable(false);
itemListTable.addColumn(column, headerText);
itemListTable.setColumnWidth(column, columnWidthPct, PCT);
return column;
}
private void generateExistingSettingsTable() {
addColumn(existingSettingsTable, new ParameterizedCheckboxCell<T>(), IS_PUBLIC_HEADER, 10, new IValueGetter<Boolean, T>() {
@Override
public Boolean getValue(T setting) {
return setting.isPublic();
}
},
new FieldUpdater<T, Boolean>() {
@Override
public void update(int index, T object, Boolean value) {
object.setPublic(value);
updatePublicState(object);
}
}
);
}
My ParameterizedCheckboxCell extends CheckboxCell and only overrides the render method (to enable / disable the checkbox).
I've already tried everything suggested here here :
- stopPropagation doesn't work for me
- Add column to blacklist DefaultSelectionEventManager, this is not an option (very large area left unlocked around the checkbox)
source to share
As I found out today, the same thing happens with Chrome (version 45.0.2454.101). I research this more and find out the following. GWT CheckboxCell
only consumes two browser events by default: keydown
and change
. In the old version of Chrome, when you clicked on the checkbox change
, the event fires and everything works fine. In FireFox and newer Chrome, there is no event after click change
(I can't figure out why explanations are welcome ), so I decided to create my own checkbox class that extends AbstractEditableCell<Boolean, Boolean>
and replace the consumed one change
with an click
event. This is what I got:
import java.util.Objects;
import com.google.gwt.cell.client.AbstractEditableCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import static com.google.gwt.dom.client.BrowserEvents.CLICK;
import static com.google.gwt.dom.client.BrowserEvents.KEYDOWN;
public class ParameterizedCheckboxCell extends AbstractEditableCell<Boolean, Boolean> {
public ParameterizedCheckboxCell() {
super(KEYDOWN, CLICK);
}
@Override
public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
// Here i have some specific logic so i skip this part
// You can just copy/paste body of this method from original CheckboxCell
}
@Override
public void onBrowserEvent(Context context, Element parent, Boolean value, NativeEvent event, ValueUpdater<Boolean> valueUpdater) {
final String type = event.getType();
final boolean enterPressed = KEYDOWN.equals(type) && event.getKeyCode() == KeyCodes.KEY_ENTER;
if (CLICK.equals(type) || enterPressed) {
InputElement input = parent.getFirstChild().cast();
Boolean isChecked = input.isChecked();
if (enterPressed) {
isChecked = !isChecked;
input.setChecked(isChecked);
}
if (Objects.equals(value, isChecked)) {
clearViewData(context.getKey());
} else {
setViewData(context.getKey(), isChecked);
}
valueUpdater.update(isChecked);
}
}
@Override
public boolean isEditing(Context context, Element parent, Boolean value) {
return false;
}
}
I missed dependsOnSelection
and handlesSelection
because I am not using this for a select column.
source to share