Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: restore

BeanEditForm is a powerful Tapestry component capable of generating a complete create/edit user interface for a typical JavaBean.

Wiki Markup
{float:right|background=#eee|padding=0 1em}
    *JumpStart Demos:*
    [Edit (Using BeanEditForm)|http://jumpstart.doublenegative.com.au/jumpstart/examples/input/edit1/1]
    [Create (Using BeanEditForm)|http://jumpstart.doublenegative.com.au/jumpstart/examples/input/create1]
    [More Control Edit (Using BeanEditor)|http://jumpstart.doublenegative.com.au/jumpstart/examples/input/morecontroledit1/1]
{float}
BeanEditForm analyzes the the properties of the bean, locating just those properties that are readable and writeable. It filters down to properties whose type is mapped to a known editor (this is described in more detail below).

...

If desired, additional validation may be specified using the @Validate annotation. See Forms and Validation BeanEditForm Guide.

As of Tapestry 5.2, validation may also be specified via the containing component's property file, using a key in the form of propertyId-validate (eg: myfield-validate=required).

...

For example, you may want to selectively use a PasswordField component:

Code Block
java
java
  <t:beaneditform object="loginCredentials">
    <p:password>
      <t:label for="password"/>
      <t:passwordfield t:id="password" value="loginCredentials.password"/>
    </p:password>
  </t:beaneditform>

The other fields will render normally (using the built-in editors).

...

The model can be created when the page is first instantiated:

Code Block
java
java
public class MyPage
{
  @Inject
  private BeanModelSource beanModelSource;
  
  @Inject
  private ComponentResources resources;

  @Property(write=false)
  @Retain
  private BeanModel model;

  @Property
  private MyBean bean;
  
  {
     model = beanModelSource.create(MyBean.class, true, resources);
     
     // Make other changes to model here.
  }  

}

And, in the component template, the built model can be passed to the BeanEditForm component explicitly:

Code Block
java
java
  <t:beaneditform object="bean" model="model"/>

Adding New Property Editors

...

DataTypeAnalyzer is a chain of command that can match properties to data types based on property type or annotations on the property. In general, DefaultDataTypeAnalyzer is used, as that only needs to consider property type. DefaultDataTypeAnalyzer matches property types to data types, based on a search up the inheritance path.

Code Block
java
java
public static void contributeDefaultDataTypeAnalyzer(MappedConfiguration<Class, String> configuration)
{
  configuration.add(BigDecimal.class, "currency");
}

You must provide an editor for the "currency" data type. An editor is a block of a page of the application; this page is not normally rendered itself, but acts as a container for one or more blocks.

Code Block
java
java
public class AppPropertyEditBlocks
{
    @Property
    @Environmental
    private PropertyEditContext context;
  
    @Component(parameters =
    { "value=context.propertyValue", "label=prop:context.label",
            "translate=prop:currencyTranslator", "validate=prop:currencyValidator",
            "clientId=prop:context.propertyId", "annotationProvider=context" })
    private TextField currency;

    @Inject
    private ComponentResources resources;

    public FieldValidator getCurrencyValidator()
    {
      return context.getValidator(currency);
    }
    
    public FieldTranslator getCurrencyTranslator()
    {
      return context.getTranslator(current);
    }
}

The hard part is the translator; this is a piece of code that understands how to format and how to parse a currency value. It must be wrapped to create a FieldTranslator.

The editor is a block inside the component template:

Code Block
java
java
  <t:block id="currency">
    <t:label for="currency"/>
    <t:textfield t:id="currency" size="10"/>
  </t:block>

Finally, we tell the BeanEditForm component about the editor via a contribution to the BeanBlockSource service:

Code Block
java
java
public static void contributeBeanBlockSource(Configuration<BeanBlockContribution> configuration)
{
  configuration.add(new BeanBlockContribution("currency", "AppPropertyEditBlocks", "currency", true));
}

Now, when the BeanEditForm sees a property of type BigDecimal, it will map that to datatype "currency" and from there to the currency block of the AppPropertyEditBlocks page of the application.