Creating Your Own Field Types

Back: Tables Next: MoreInformation

There are times when you may want to implement your own Fields (net.sourceforge.wicketwebbeans.fields.Field). net.sourceforge.wicketwebbeans.fields.AbstractField is the base class for the Field interface. It is recommended that you use the AbstractField base class, or an extension of it, if your field will participate in a BeanForm.

By convention, all Fields must define a constructor with the signature:

	public SomeField(String id, IModel model, ElementMetaData metaData, boolean viewOnly)

In this example, we're going to enhance the net.sourceforge.wicketwebbeans.examples.customfields.Address bean to add a Country property. The Country property will be a non-Java enumeration. While Java enums are statically defined at compile-time, there are cases where you need to derive the values at runtime - let's say from a database. To make things simpler for you, WWB defines an interface called net.sourceforge.wicketwebbeans.model.NonJavaEnum. It also has a base class for this interface called net.sourceforge.wicketwebbeans.model.BaseNonJavaEnum. So let's look at our net.sourceforge.wicketwebbeans.examples.customfields.Country enumeration:

01 package net.sourceforge.wicketwebbeans.examples.customfields;
02 
03 import java.util.ArrayList;
04 import java.util.List;
05 
06 import net.sourceforge.wicketwebbeans.model.BaseNonJavaEnum;
07 
08 
09 public class Country extends BaseNonJavaEnum
10 {
11     private volatile static List<Country> cachedEnums;
12 
13     public Country(String name, String displayValue)
14     {
15         super(name, displayValue);
16     }
17 
18     /**
19      * Get the enumerated values.
20      *
21      @return the list of values. An empty list is returned if nothing is found.
22      */
23     public static List<Country> values()
24     {
25         if (cachedEnums == null) {
26             // This is where you would load a list of countries from a database. 
27             cachedEnums = new ArrayList<Country>();
28             cachedEnums.addnew Country("USA""United States") );
29             cachedEnums.addnew Country("CAN""Canada") );
30             cachedEnums.addnew Country("MEX""Mexico") );
31             cachedEnums.addnew Country("GBR""Great Britian") );
32             cachedEnums.addnew Country("RUS""Russia") );
33         }
34 
35         return cachedEnums;
36     }
37 
38     /**
39      * Get the country enum value for the given name.
40      *
41      @param enumValue name to match
42      *
43      @return a Country, or null if not found.
44      */
45     public static Country valueOf(String enumValue)
46     {
47         return (Country)BaseNonJavaEnum.valueOf(enumValue, values());
48     }
49 
50 }
Java2html

You would normally query the database for countries in the static values() method. However, we don't have a database, so we just hard coded them. The idea is that you would retrieve these values at runtime. The static values() and valueOf() methods are similar to those found on a Java language enum.

Next we need to implement the Field. WWB has a base Field class net.sourceforge.wicketwebbeans.fields.EnumField that can be used for Java enums and NonJavaEnums. Here's our net.sourceforge.wicketwebbeans.examples.customfields.CountryField that extends EnumField:

01 package net.sourceforge.wicketwebbeans.examples.customfields;
02 
03 import net.sourceforge.wicketwebbeans.fields.EnumField;
04 import net.sourceforge.wicketwebbeans.model.ElementMetaData;
05 
06 import org.apache.wicket.model.IModel;
07 
08 public class CountryField extends EnumField
09 {
10     public CountryField(String id, IModel model, ElementMetaData metaData, boolean viewOnly)
11     {
12         super(id, model, metaData, viewOnly, Country.values());
13     }
14 }
Java2html

Next, we need to register the CountryField type so that whenever WWB sees a Country bean, it will know how to handle it. In this example, this is done in net.sourceforge.wicketwebbeans.examples.customfields.CustomFieldPage:

01 package net.sourceforge.wicketwebbeans.examples.customfields;
02 
03 import net.sourceforge.wicketwebbeans.containers.BeanForm;
04 import net.sourceforge.wicketwebbeans.model.BeanMetaData;
05 import net.sourceforge.wicketwebbeans.model.ComponentRegistry;
06 
07 import org.apache.wicket.markup.html.WebPage;
08 
09 public class CustomFieldPage extends WebPage
10 {
11     public CustomFieldPage()
12     {
13         Address bean = new Address();
14         
15         // Register the ModelField for the Country class.
16         ComponentRegistry registry = new ComponentRegistry();
17         registry.register(Country.class, CountryField.class);
18         
19         BeanMetaData meta = new BeanMetaData(bean.getClass(), null, this, registry, false);
20         addnew BeanForm("beanForm", bean, meta) );
21     }
22 }
Java2html

For simplicity, we add the mapping to ComponentRegistry directly in our Page code. However, you would normally create your instance or sub-class of ComponentRegistry outside of the Page code so that it can be used from multiple pages.

The end result looks like this:

Eclipse:/WicketWebBeans/doc/wiki/images/CustomFieldScreenshot.png

Back: Tables Next: MoreInformation