Thursday, August 1, 2013

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. 

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

No comments:

Post a Comment