Form binding is the process of binding the properties of a domain object with the fields of a form.In modern web development form binding can be very useful since there is no need to manually process the submitted values and update the domain objects with them.

In Apache Wicket framework domain objects can be bounded to form fields mainly using PropertyModel and CompoundPropertyModel and in this tutorial we will see how they are used.
 

Using PropertyModel

PropertyModel can dynamically bind the properties of an object to form fields.In order to do that PropertyModel is using an expression language to set or retrieve the values of the object. As an example consider the case where we need to build a registration form and save it's fields at a Person object.

In this case the Person class would be:

import java.io.Serializable;


public class Person implements Serializable{

private String name;

private String surname;

private Integer age;

private String username;

private String password;

public String getName() {

return name;

}


public void setName(String name) {

this.name = name;

}


public String getSurname() {

return surname;

}


public void setSurname(String surname) {

this.surname = surname;

}


public Integer getAge() {

return age;

}


public void setAge(Integer age) {

this.age = age;

}


public String getUsername() {

return username;

}


public void setUsername(String username) {

this.username = username;

}


public String getPassword() {

return password;

}


public void setPassword(String password) {

this.password = password;

}

}

The form would be:

 

<form wicket:id="formTest">
            <table>
                <tr><td>Name:</td><td><input type="text"
wicket:id="name"/></td></tr>
                <tr><td>Surname:</td><td><input type="text"
wicket:id="surname"/></td></tr>
                <tr><td>Age:</td><td><input type="text"
wicket:id="age"/></td></tr>
                <tr><td>Username:</td><td><input type="text"
wicket:id="username"/></td></tr>
                <tr><td>Password:</td><td><input type="password"
wicket:id="password"/></td></tr>
                <tr><td><input type="submit" value="Submit"/></td></tr>
            </table>
        </form>

The webpage class using propertyModels would look something like:

public final class PropertModelForm extends WebPage {


private Form form;

private TextField nameField;

private TextField surnameField;

private TextField ageField;

private TextField usernameField;

private PasswordTextField passwordField;

private PropertyModel nameModel;

private PropertyModel surnameModel;

private PropertyModel ageModel;

private PropertyModel usernameModel;

private PropertyModel passwordModel;

private Person person;

public PropertModelForm() {

super();

person=new Person();

//Initialize models

nameModel=new PropertyModel(person,"name");

surnameModel=new PropertyModel(person,"surname");

ageModel=new PropertyModel(person, "age");

usernameModel=new PropertyModel(person,"username");

passwordModel=new PropertyModel(person,"password");

//Initialize textFields

nameField=new TextField("name",nameModel);

surnameField=new TextField("surname",surnameModel);

ageField=new TextField("age",ageModel,Integer.class);

usernameField=new TextField("username",usernameModel);

passwordField=new PasswordTextField("password",passwordModel);

form=new Form("formTest"){


@Override

protected void onSubmit() {

System.out.println("TEST");

Person somebody=(Person)getModelObject();

System.out.println("PERSON NAME:"+somebody.getName());

}

};

//add textFields to the form

form.add(nameField);

form.add(surnameField);

form.add(ageField);

form.add(usernameField);

form.add(passwordField);

//add form to webpage

add(form);

}

}

 Now suppose that the user should also submit her address data and the Person object has also an Address property.The Address object would be:
 

public class Adress implements Serializable{

private String street;

private String zipcode;

private String city;


public String getStreet() {

return street;

}


public void setStreet(String street) {

this.street = street;

}


public String getZipcode() {

return zipcode;

}


public void setZipcode(String zipcode) {

this.zipcode = zipcode;

}


public String getCity() {

return city;

}


public void setCity(String city) {

this.city = city;

}

}

And the address property in Person class would be:

private Address address;

In our form we add the following fields:

<tr><td>Street:</td><td><input type="text" wicket:id="street"/></td></tr>
<tr><td>Zip:</td><td><input type="text" wicket:id="zip"/></td></tr>
<tr><td>City:</td><td><input type="text" wicket:id="city"/></td></tr>

and now the web page class should be:


package com.myapp.wicket.pages;


import com.myapp.wicket.model.Person;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.PropertyModel;


public final class PropertModelForm extends WebPage {

    private Form form;
    private TextField nameField;
    private TextField surnameField;
    private TextField ageField;
    private TextField usernameField;
    private TextField streetField;
    private TextField zipField;
    private TextField cityField;
    private PasswordTextField passwordField;
    private PropertyModel nameModel;
    private PropertyModel surnameModel;
    private PropertyModel ageModel;
    private PropertyModel usernameModel;
    private PropertyModel passwordModel;
    private PropertyModel streetModel;
    private PropertyModel zipModel;
    private PropertyModel cityModel;
    private Person person;
    public PropertModelForm() {
        super();
        person=new Person();
        
        //Initialize models
        nameModel=new PropertyModel(person,"name");
        surnameModel=new PropertyModel(person,"surname");
        ageModel=new PropertyModel(person, "age");
        usernameModel=new PropertyModel(person,"username");
        passwordModel=new PropertyModel(person,"password");
        streetModel=new PropertyModel(person,"address.street");
        zipModel=new PropertyModel(person,"address.zip");
        cityModel=new PropertyModel(person,"address.city");
        
        //Initialize textFields
        nameField=new TextField("name",nameModel);
        surnameField=new TextField("surname",surnameModel);
        ageField=new TextField("age",ageModel,Integer.class);
        usernameField=new TextField("username",usernameModel);
        passwordField=new PasswordTextField("password",passwordModel);
        streetField=new TextField("street",streetModel);
        zipField=new TextField("zip",zipModel);
        cityField=new TextField("city",cityModel);
        form=new Form("formTest"){

            @Override
            protected void onSubmit() {
                System.out.println("TEST");
                Person somebody=(Person)getModelObject();
                System.out.println("PERSON NAME:"+somebody.getName());
            }
        
            
        };
        //add textFields to the form
        form.add(nameField);
        form.add(surnameField);
        form.add(ageField);
        form.add(usernameField);
        form.add(passwordField);
        form.add(streetField);
        form.add(zipField);
        form.add(cityField);
        //add form to webpage
        add(form);
    }
    
    
}

In the above class note that in order to access the Address properties we used:

streetModel=new PropertyModel(person,"address.street");
        zipModel=new PropertyModel(person,"address.zip");
        cityModel=new PropertyModel(person,"address.city");

Using CompoundPropertyModel
Although proertyModels are quite useful we could save some coding and objects by using CompoundPropertyModel instead of propertyModels.The main difference is that CompoundPropertyModel is bounded on the contaier-in our case the form- and as a result we don't have to instantiate a propertyModel for every property of our object.
Using CompoundPropertyModel the web page class would be:


package com.myapp.wicket.pages;

import com.myapp.wicket.model.Person;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;


public final class PropertModelForm extends WebPage {

    private Form form;
    private TextField nameField;
    private TextField surnameField;
    private TextField ageField;
    private TextField usernameField;
    private TextField streetField;
    private TextField zipField;
    private TextField cityField;
    private PasswordTextField passwordField;
    private Person person;

    public PropertModelForm() {
        super();
        person = new Person();



        //Initialize textFields
        nameField = new TextField("name");
        surnameField = new TextField("surname");
        ageField = new TextField("age", Integer.class);
        usernameField = new TextField("username");
        passwordField = new PasswordTextField("password");
        streetField = new TextField("address.street");
        zipField = new TextField("address.zip");
        cityField = new TextField("address.city");
        form = new Form("formTest", new CompoundPropertyModel(getPerson())) {

            @Override
            protected void onSubmit() {
                System.out.println("TEST");
                Person somebody = (Person) getModelObject();
                System.out.println("PERSON NAME:" + somebody.getName());
            }
        };
        //add textFields to the form
        form.add(nameField);
        form.add(surnameField);
        form.add(ageField);
        form.add(usernameField);
        form.add(passwordField);
        form.add(streetField);
        form.add(zipField);
        form.add(cityField);
        //add form to webpage
        add(form);
    }

    public Person getPerson() {
        return person;
    }

   
    public void setPerson(Person person) {
        this.person = person;
    }
}

and the form in the html page would be:

<form wicket:id="formTest">
            <table>
                <tr><td>Name:</td><td><input type="text" wicket:id="name"/></td></tr>
                <tr><td>Surname:</td><td><input type="text" wicket:id="surname"/></td></tr>
                <tr><td>Age:</td><td><input type="text" wicket:id="age"/></td></tr>
                <tr><td>Username:</td><td><input type="text" wicket:id="username"/></td></tr>
                <tr><td>Password:</td><td><input type="password" wicket:id="password"/></td></tr>
                <tr><td>Street:</td><td><input type="text" wicket:id="address.street"/></td></tr>
                <tr><td>Zip:</td><td><input type="text" wicket:id="address.zip"/></td></tr>
                <tr><td>City:</td><td><input type="text" wicket:id="address.city"/></td></tr>
                <tr><td><input type="submit" value="Submit"/></td></tr>
            </table>
        </form>

You may have noticed the differences in the above class and form.First of all the TextFields are instantiated using only the name of the form field which is also the name of the property in the Person object.Furthermore in order to access the field of the address object we used the same expressions as we did when we used property models.