Tessell

Checkbox Example

A simple example of binding a property to a checkbox and doing some logic based on the selected value.

We’ll start with a really simple template file, that just has a CheckBox and a Label:

CheckboxExample.ui.xml:


<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:gwt="urn:import:com.google.gwt.user.client.ui">
  <gwt:HTMLPanel>
    <p>
      <gwt:CheckBox ui:field="box" text="Box" />
    </p>
    <p>
      <gwt:InlineLabel ui:field="label" />
    </p>
  </gwt:HTMLPanel>
</ui:UiBinder>

Which, from this, Tessell will generate the view interface:

IsCheckboxExampleView.java


package org.tessell.examples.client.views;

import org.tessell.gwt.user.client.ui.IsCheckBox;
import org.tessell.gwt.user.client.ui.IsInlineLabel;
import org.tessell.gwt.user.client.ui.IsWidget;

public interface IsCheckboxExampleView extends IsWidget {

    public IsCheckBox box();

    public IsInlineLabel label();

    public void ensureDebugIdSuffix(String suffix);

}

For our example, we just want to:

With Tessell’s stub widgets, we could actually implement this the old fashioned way, with event handlers:

view.box().addValueChangedHandler(new ValueChangedHandler<Boolean>()) {
  public void onValueChange(ValueChangeEvent<Boolean> event) {
    view.label().setText(event.getValue() ? "Checked!" : "Not checked");
  }
}

But, for the purposes of this example, we’ll use Tessell’s reactive features to bind the checkbox to a property, create a derived property, and bind that derived property to the label.

CheckboxExamplePresenter.java:


package org.tessell.examples.client.app;

import static org.tessell.examples.client.views.AppViews.newCheckboxExampleView;
import static org.tessell.model.dsl.TakesValues.textOf;
import static org.tessell.model.properties.NewProperty.booleanProperty;

import org.tessell.examples.client.views.IsCheckboxExampleView;
import org.tessell.model.properties.BooleanProperty;
import org.tessell.model.properties.DerivedProperty;
import org.tessell.presenter.BasicPresenter;

/** An example of checkbox binding. */
public class CheckboxExamplePresenter extends BasicPresenter<IsCheckboxExampleView> {

  private final BooleanProperty checked = booleanProperty("checked");

  public CheckboxExamplePresenter() {
    super(newCheckboxExampleView());
  }

  @Override
  public void onBind() {
    super.onBind();

    // two-way binding between checked and view.box()
    binder.bind(checked).to(view.box());

    // two-way binding between our derived value and view.label()'s text
    binder.bind(new DerivedProperty<String>() {
      protected String getDerivedValue() {
        return checked.isTrue() ? "Checked!" : "Not checked";
      }
    }).to(textOf(view.label()));
  }

}

Since the DerivedProperty we create uses checked.isTrue(), any time checked changes, our getDerivedValue() method will be called, and the derived property will update itself.

And since we’ve bound the DerivedProperty to the view.label(), then the label’s text will also get updated.

We can unit test this functionality in a presenter test:

CheckboxExamplePresenterTest.java:


package org.tessell.examples.client.app;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.Test;
import org.tessell.examples.client.views.StubCheckboxExampleView;

public class CheckboxExamplePresenterTest extends AbstractPresenterTest {

  private final CheckboxExamplePresenter p = bind(new CheckboxExamplePresenter());
  private final StubCheckboxExampleView v = (StubCheckboxExampleView) p.getView();

  @Test
  public void defaultsToNotChecked() {
    assertThat(v.label().getText(), is("Not checked"));
  }

  @Test
  public void checkingSetsTheLabel() {
    v.box().check();
    assertThat(v.label().getText(), is("Checked!"));
  }
  
  @Test
  public void uncheckingUnsetsTheLabel() {
    v.box().check();
    v.box().uncheck();
    assertThat(v.label().getText(), is("Not checked"));
  }

}