Integration example

There are two ways in which you can compose a form:

  • using a simple form
  • using a Model-View concept
In the introduction you can find an example using a simple form. Here you can find a detailed example using a model/view concept.

Example
Create new user

The underlying XML template (with message id="userForm-template") uses style classes from the Bootstrap theme. In order to apply validation style to any widget with invalid input, you should group the widgets in a div or span section and apply the style input-group to it.

source
<legend>${title}</legend>
<div class="row">
<div class="col-4">
<label class="form-label" for="${id:first-name}">
First name
</label>
${first-name}
<div class="form-text">
${first-name-info}
</div>
</div>
<div class="col-4">
<label class="form-label" for="${id:last-name}">
Last name
</label>
${last-name}
<div class="form-text">
${last-name-info}
</div>
</div>
</div>

<div class="row">
<div class="col-4">
<label class="form-label" for="${id:country}">
Country
</label>
${country}
<div class="form-text">
${country-info}
</div>
</div>
<div class="col-4">
<label class="form-label" for="${id:city}">
City
</label>
${city}
<div class="form-text">
${city-info}
</div>
</div>
</div>

<div class="row">
<div class="col-4">
<label class="form-label" for="${id:birth}">
Birth date
</label>
${birth}
<div class="form-text">
${birth-info}
</div>
</div>

<div class="col-4">
<label class="form-label" for="${id:children}">
Children
</label>
${children}
<div class="form-text">
${children-info}
</div>
</div>
</div>

<div class="row">
<div class="col-8">
<label class="form-label" for="${id:remarks}">
Remarks
</label>
${remarks}
<div class="form-text">
${remarks-info}
</div>
</div>
</div>

<div class="row">
<div class="col">
${submit-button} <span class="help-inline">${submit-info}</span>
</div>
</div>

Here is the implementation of WFormModel and WTemplateFormView.

There are created validators for several fields. See the section Validation for more details on validators, especially a more elaborated example on a WDateValidator for a WDatePicker.

source
  class UserFormModel extends WFormModel {
    private static Logger logger = LoggerFactory.getLogger(UserFormModel.class);

    public static final String FirstNameField = "first-name";
    public static final String LastNameField = "last-name";
    public static final String CountryField = "country";
    public static final String CityField = "city";
    public static final String BirthField = "birth";
    public static final String ChildrenField = "children";
    public static final String RemarksField = "remarks";

    UserFormModel() {
      super();
      this.countryModel_ = null;
      this.cityModel_ = null;
      this.initializeModels();
      this.addField(FirstNameField);
      this.addField(LastNameField);
      this.addField(CountryField);
      this.addField(CityField);
      this.addField(BirthField);
      this.addField(ChildrenField);
      this.addField(RemarksField);
      this.setValidator(FirstNameField, this.createNameValidator(FirstNameField));
      this.setValidator(LastNameField, this.createNameValidator(LastNameField));
      this.setValidator(CountryField, this.createCountryValidator());
      this.setValidator(CityField, this.createCityValidator());
      this.setValidator(BirthField, this.createBirthValidator());
      this.setValidator(ChildrenField, this.createChildrenValidator());
      this.setValue(BirthField, null);
      this.setValue(CountryField, "");
    }

    WAbstractItemModel getCountryModel() {
      return this.countryModel_;
    }

    int countryModelRow(final String code) {
      for (int i = 0; i < this.countryModel_.getRowCount(); ++i) {
        if (this.countryCode(i).equals(code)) {
          return i;
        }
      }
      return -1;
    }

    WAbstractItemModel getCityModel() {
      return this.cityModel_;
    }

    void updateCityModel(final String countryCode) {
      this.cityModel_.clear();
      List<String> i = cities.get(countryCode);
      if (i != null) {
        final List<String> cities = i;
        this.cityModel_.appendRow(new WStandardItem());
        for (int j = 0; j < cities.size(); ++j) {
          this.cityModel_.appendRow(new WStandardItem(cities.get(j)));
        }
      } else {
        this.cityModel_.appendRow(new WStandardItem("(Choose Country first)"));
      }
    }

    WString getUserData() {
      return StringUtils.asString(this.getValue(FirstNameField))
          .append(" ")
          .append(StringUtils.asString(this.getValue(LastNameField)))
          .append(": country code=")
          .append(StringUtils.asString(this.getValue(CountryField)))
          .append(", city=")
          .append(StringUtils.asString(this.getValue(CityField)))
          .append(", birth=")
          .append(StringUtils.asString(this.getValue(BirthField)))
          .append(", children=")
          .append(StringUtils.asString(this.getValue(ChildrenField)))
          .append(", remarks=")
          .append(StringUtils.asString(this.getValue(RemarksField)))
          .append(".");
    }

    String countryCode(int row) {
      return StringUtils.asString(this.countryModel_.getData(row, 0, ItemDataRole.User)).toString();
    }

    private static final Map<String, List<String>> cities = getCityMap();
    private static final Map<String, String> countries = getCountryMap();
    private WStandardItemModel countryModel_;
    private WStandardItemModel cityModel_;
    private static final int MAX_LENGTH = 25;
    private static final int MAX_CHILDREN = 15;

    void initializeModels() {
      int countryModelRows = countries.size() + 1;
      final int countryModelColumns = 1;
      this.countryModel_ = new WStandardItemModel(countryModelRows, countryModelColumns);
      int row = 0;
      this.countryModel_.setData(row, 0, " ", ItemDataRole.Display);
      this.countryModel_.setData(row, 0, "", ItemDataRole.User);
      row = 1;
      for (Iterator<Map.Entry<String, String>> i_it = countries.entrySet().iterator();
          i_it.hasNext(); ) {
        Map.Entry<String, String> i = i_it.next();
        this.countryModel_.setData(row, 0, i.getValue(), ItemDataRole.Display);
        this.countryModel_.setData(row++, 0, i.getKey(), ItemDataRole.User);
      }
      this.cityModel_ = new WStandardItemModel();
      this.updateCityModel("");
    }

    WValidator createNameValidator(final String field) {
      WLengthValidator v = new WLengthValidator();
      v.setMandatory(true);
      v.setMinimumLength(1);
      v.setMaximumLength(MAX_LENGTH);
      return v;
    }

    WValidator createCountryValidator() {
      WLengthValidator v = new WLengthValidator();
      v.setMandatory(true);
      return v;
    }

    WValidator createCityValidator() {
      WLengthValidator v = new WLengthValidator();
      v.setMandatory(true);
      return v;
    }

    WValidator createBirthValidator() {
      WDateValidator v = new WDateValidator();
      v.setBottom(new WDate(1900, 1, 1));
      v.setTop(WDate.getCurrentDate());
      v.setFormat("dd/MM/yyyy");
      v.setMandatory(true);
      return v;
    }

    WValidator createChildrenValidator() {
      WIntValidator v = new WIntValidator(0, MAX_CHILDREN);
      v.setMandatory(true);
      return v;
    }
  }

  Map<String, String> getCountryMap() {
    Map<String, String> retval = new HashMap<String, String>();
    retval.put("BE", "Belgium");
    retval.put("NL", "Netherlands");
    retval.put("UK", "United Kingdom");
    retval.put("US", "United States");
    return retval;
  }

  Map<String, List<String>> getCityMap() {
    List<String> beCities = new ArrayList<String>();
    beCities.add("Antwerp");
    beCities.add("Bruges");
    beCities.add("Brussels");
    beCities.add("Ghent");
    List<String> nlCities = new ArrayList<String>();
    nlCities.add("Amsterdam");
    nlCities.add("Eindhoven");
    nlCities.add("Rotterdam");
    nlCities.add("The Hague");
    List<String> ukCities = new ArrayList<String>();
    ukCities.add("London");
    ukCities.add("Bristol");
    ukCities.add("Oxford");
    ukCities.add("Stonehenge");
    List<String> usCities = new ArrayList<String>();
    usCities.add("Boston");
    usCities.add("Chicago");
    usCities.add("Los Angeles");
    usCities.add("New York");
    Map<String, List<String>> retval = new HashMap<String, List<String>>();
    retval.put("BE", beCities);
    retval.put("NL", nlCities);
    retval.put("UK", ukCities);
    retval.put("US", usCities);
    return retval;
  }

  class UserFormView extends WTemplateFormView {
    private static Logger logger = LoggerFactory.getLogger(UserFormView.class);

    UserFormView(WContainerWidget parentContainer) {
      super();
      this.model = null;
      this.model = new UserFormModel();
      this.setTemplateText(tr("userForm-template"));
      this.addFunction("id", WTemplate.Functions.id);
      this.addFunction("block", WTemplate.Functions.id);
      this.setFormWidget(UserFormModel.FirstNameField, new WLineEdit());
      this.setFormWidget(UserFormModel.LastNameField, new WLineEdit());
      WComboBox countryCB = new WComboBox();
      final WComboBox countryCB_ = countryCB;
      countryCB.setModel(this.model.getCountryModel());
      countryCB_
          .activated()
          .addListener(
              this,
              () -> {
                String code = UserFormView.this.model.countryCode(countryCB_.getCurrentIndex());
                UserFormView.this.model.updateCityModel(code);
              });
      this.setFormWidget(
          UserFormModel.CountryField,
          countryCB,
          () -> {
            String code =
                StringUtils.asString(UserFormView.this.model.getValue(UserFormModel.CountryField))
                    .toString();
            int row = UserFormView.this.model.countryModelRow(code);
            countryCB_.setCurrentIndex(row);
          },
          () -> {
            String code = UserFormView.this.model.countryCode(countryCB_.getCurrentIndex());
            UserFormView.this.model.setValue(UserFormModel.CountryField, code);
          });
      WComboBox cityCB = new WComboBox();
      cityCB.setModel(this.model.getCityModel());
      this.setFormWidget(UserFormModel.CityField, cityCB);
      WDateEdit dateEdit = new WDateEdit();
      final WDateEdit dateEdit_ = dateEdit;
      this.setFormWidget(
          UserFormModel.BirthField,
          dateEdit,
          () -> {
            WDate date = ((WDate) UserFormView.this.model.getValue(UserFormModel.BirthField));
            dateEdit_.setDate(date);
          },
          () -> {
            WDate date = dateEdit_.getDate();
            UserFormView.this.model.setValue(UserFormModel.BirthField, date);
          });
      this.setFormWidget(UserFormModel.ChildrenField, new WSpinBox());
      WTextArea remarksTA = new WTextArea();
      remarksTA.setColumns(40);
      remarksTA.setRows(5);
      this.setFormWidget(UserFormModel.RemarksField, remarksTA);
      WString title = new WString("Create new user");
      this.bindString("title", title);
      WPushButton button = new WPushButton("Save");
      this.bindWidget("submit-button", button);
      this.bindString("submit-info", new WString());
      button
          .clicked()
          .addListener(
              this,
              (WMouseEvent e1) -> {
                UserFormView.this.process();
              });
      this.updateView(this.model);
      if (parentContainer != null) parentContainer.addWidget(this);
    }

    public UserFormView() {
      this((WContainerWidget) null);
    }

    void process() {
      this.updateModel(this.model);
      if (this.model.validate()) {
        this.bindString(
            "submit-info",
            new WString("Saved user data for ").append(this.model.getUserData()),
            TextFormat.Plain);
        this.updateView(this.model);
        WLineEdit viewField = (WLineEdit) this.resolveWidget(UserFormModel.FirstNameField);
        viewField.setFocus(true);
      } else {
        this.bindEmpty("submit-info");
        this.updateView(this.model);
      }
    }

    private UserFormModel model;
  }

  void FormModel() {
    UserFormView view = new UserFormView();
  }

Top