Should you be using "listener:save" and "listener:delete" rather than
"ognl:listeners.save" and "ognl:listeners.delete"?

On 5/1/06, Apache Wiki <[EMAIL PROTECTED]> wrote:
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Jakarta-tapestry Wiki" 
for change notification.

The following page has been changed by DanielGredler:
http://wiki.apache.org/jakarta-tapestry/BeanForm

The comment on the change is:
Validation support, other small tweaks.

------------------------------------------------------------------------------
  An [http://howardlewisship.com/blog/2006/03/from-fanciful-ideas-category.html 
often-requested feature] is an easier, more Trails-like way of editing domain 
objects that gets rid of a lot of the boilerplate typing required to create an 
edit form. 
[http://planesailing.blogspot.com/2006/03/tapestry-edit-component.html Some 
solutions] are breathtaking in their comprehensiveness but suffer from lack of 
documentation and over-architecting (imho). The BeanForm is a simpler solution 
to this common problem:

+ {{{
- {{{<span jwcid="@BeanForm" bean="ognl:pojo" save="ognl:listeners.save" 
delete="ognl:listeners.delete"/>}}}
+ <span jwcid="@BeanForm" bean="ognl:pojo" save="ognl:listeners.save" 
delete="ognl:listeners.delete"/>
+ }}}

- The above code gets you a form that will call save() when submitted for save, 
delete() when submitted for delete, displays a !TextField for every string or 
number property, a Checkbox for every boolean property and a !DatePicker for 
every date property, and automatically disables fields for read-only 
properties. Properties are discovered via 
[http://java.sun.com/docs/books/tutorial/javabeans/index.html bean 
introspection]. You can use the BeanForm with a single line, as above, or you 
can include it inside one of your existing Forms, in which case the internal 
Form component will not be generated. It's your choice.
+ The above code gets you a form that will call save() when submitted for save, 
delete() when submitted for delete, displays !TextFields for the bean's string 
and numerical properties, Checkboxes for its boolean properties and 
!DatePickers for its date properties, and automatically disables fields for 
read-only properties. Properties are discovered via 
[http://java.sun.com/docs/books/tutorial/javabeans/index.html bean 
introspection]. You can use the BeanForm with a single line, as above, or you 
can include it inside one of your existing Forms, in which case the internal 
Form component will not be generated. It's your choice.

- You can also specify exactly which properties you want included in the 
BeanForm, as well as cancel and refresh listeners. When you explicitly specify 
editable properties, those properties are shown on the page in the order you 
specify:
+ You can also specify exactly which properties you want included in the 
BeanForm, as well as cancel and refresh listeners and any of the other 
parameters supported by the 
[http://jakarta.apache.org/tapestry/tapestry/ComponentReference/Form.html Form 
component]. When you explicitly specify the editable properties, those 
properties are shown on the page in the order you specify:

+ {{{
- {{{<span jwcid="@BeanForm" bean="ognl:pojo" properties="ognl:'name,email,comment'" 
save="ognl:listeners.save" cancel="ognl:listeners.cancel" refresh="ognl:listeners.refresh" />}}}
+ <span jwcid="@BeanForm" bean="ognl:pojo" properties="ognl:'name,email,comment'" 
save="ognl:listeners.save" cancel="ognl:listeners.cancel" refresh="ognl:listeners.refresh" />
+ }}}

  The generated HTML is a form containing a two-column table (unless the 
BeanForm is already inside a Form, in which case another Form is not 
generated). The left column contains the field labels and the right column 
contains the data entry fields. The bottom row spans both columns and contains 
the save button, the cancel button (if the ''cancel'' parameter was specified), 
the refresh button (if the ''refresh'' parameter was specified) and the delete 
button (if the ''delete'' parameter was specified). The table can be styled 
using CSS: the table's CSS class is ''beanFormTable'', the left column's CSS 
class is ''beanFormLeftColumn'', the right column's CSS class is 
''beanFormRightColumn'', and the bottom column that contains the buttons has 
the CSS class ''beanFormButtonColumn''.

- If you need to customize any of the input fields, you can do so by adding a Block component to 
your page (with the id ''"[propertyName]!BeanFieldBlock"'') that contains any 
I!FormComponent (with the id ''"[propertyName]!BeanField"''). For example, if you wanted 
to edit the ''comment'' property in a text area instead of the default textfield, you could add the 
following to your page:
+ If you need to customize any of the input fields, you can do so by adding a Block component to 
your page (with the id ''"[propertyName]!BeanFieldBlock"'') that contains any 
I!FormComponent (with the id ''"[propertyName]!BeanField"''). Doing this will also allow 
you to edit properties that are considered non-editable by default (ie, not a string / boolean / 
number / date).

+ For example, if you wanted to edit the ''comment'' property in a !TextArea 
instead of the default textfield, you could add the following to your page:
+
+ {{{
+ <div jwcid="[EMAIL PROTECTED]">
- {{{<div jwcid="[EMAIL PROTECTED]"><input jwcid="[EMAIL PROTECTED]" value="ognl:pojo.comment" 
displayName="message:comment"/></div>}}}
+       <input jwcid="[EMAIL PROTECTED]" value="ognl:pojo.comment" 
displayName="message:comment"/>
+ </div>
+ }}}
+
+ In order to use validation, specify the ''delegate'' parameter (unless you 
have already specified it in an external Form component that contains this 
component) and add standard Tapestry 
[http://jakarta.apache.org/tapestry/UsersGuide/validation.html validator lists] 
to the ''properties'' parameter, in between squiggly brackets (''{ }''). Fox 
example, if you want to make the ''name'' and ''email'' properties required, 
and want to check that ''email'' is actually an email address, you could do the 
following:
+
+ {{{
+ <span jwcid="@BeanForm" bean="ognl:pojo" properties="ognl:'name{required},email{required,email},comment'" 
save="ognl:listeners.save" delegate="ognl:beans.validationDelegate" clientValidationEnabled="ognl:true"/>
+ }}}

  Internationalization is supported out of the box: field labels are messages 
keyed on the property name. The save button (if displayed) is labeled with the 
message corresponding to the key ''save''. The cancel button (if displayed) is 
labeled with the message corresponding to the key ''cancel''. The refresh 
button (if displayed) is labeled with the message corresponding to the key 
''refresh''.  The delete button (if displayed) is labeled with the message 
corresponding to the key ''delete''.

- All of this is done in ~400 lines of (Java + XML + HTML) and is simple enough 
that when you need that one extra feature, you can just enhance this code 
rather than going back to boilerplateland. All constructive criticism is 
welcome. Enjoy!
+ This component should be simple enough that when you need that one extra 
feature, you can just enhance this code rather than going back to 
boilerplateland. Enjoy!

  Three files:
   * BeanForm.java
@@ -91, +107 @@

  import java.beans.SimpleBeanInfo;
  import java.io.Serializable;
  import java.util.ArrayList;
- import java.util.Arrays;
  import java.util.Date;
+ import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
+ import java.util.regex.Matcher;
+ import java.util.regex.Pattern;

  import org.apache.hivemind.ApplicationRuntimeException;
+ import org.apache.hivemind.Location;
  import org.apache.tapestry.BaseComponent;
  import org.apache.tapestry.IComponent;
  import org.apache.tapestry.IRequestCycle;
  import org.apache.tapestry.TapestryUtils;
  import org.apache.tapestry.annotations.InjectObject;
+ import org.apache.tapestry.binding.BindingFactory;
  import org.apache.tapestry.components.Block;
  import org.apache.tapestry.form.IFormComponent;
+ import org.apache.tapestry.form.validator.ValidatorsBinding;

  import com.diphy.util.Logger;

  /**
-  * <p>A form that provides edit capabilities for a Java Bean. Only properties 
that are
+  * <p>A form that provides edit capabilities for a Java Bean. Only properties
-  * strings, booleans, numbers or dates are considered editable. Fields for 
read-only
+  * that are strings, booleans, numbers or dates are considered editable. 
Fields
-  * bean properties are automatically disabled. Field labels are messages 
keyed on the
+  * for read-only bean properties are automatically disabled. Field labels are
+  * messages keyed on the property name. The save button (if displayed) is
+  * labeled with the message corresponding to the key <tt>save</tt>. The cancel
-  * property name. The save button (if displayed) is labeled with the message 
corresponding to
+  * button (if displayed) is labeled with the message corresponding to the key
-  * the key <tt>save</tt>. The cancel button (if displayed) is labeled with 
the message
+  * <tt>cancel</tt>. The refresh button (if displayed) is labeled with the
-  * corresponding to the key <tt>cancel</tt>. The refresh button (if 
displayed) is labeled
-  * with the message corresponding to the key <tt>refresh</tt>. The delete 
button (if
+  * message corresponding to the key <tt>refresh</tt>. The delete button (if
-  * displayed) is labeled with the message corresponding to the key 
<tt>delete</tt>.</p>
+  * displayed) is labeled with the message corresponding to the key
+  * <tt>delete</tt>.</p>
   *
   * <p>The component parameters are as follows:</p>
   *
   * <ul>
   *   <li><tt>bean</tt>: Required, specifies the Java Bean to modify.</li>
-  *   <li><tt>properties</tt>: Not required, specifies the bean properties to 
be edited; if omitted,
+  *   <li><tt>properties</tt>: Not required, specifies the bean properties to 
be
-  *      all eligible bean properties (strings, booleans, numbers and dates) 
are considered
-  *      editable; if specified, properties are displayed in the specified 
order.</li>
+  *      edited; if omitted, all eligible bean properties (strings, booleans,
+  *      numbers and dates) are considered editable; if specified, properties
+  *      are displayed in the specified order.</li>
-  *   <li><tt>save</tt>: Not required, specifies the listener to invoke on 
save.</li>
+  *   <li><tt>save</tt>: Not required, specifies the listener to invoke on
+  *      save.</li>
-  *   <li><tt>delete</tt>: Not required, specifies the listener to invoke on 
delete.</li>
+  *   <li><tt>delete</tt>: Not required, specifies the listener to invoke on
+  *      delete.</li>
-  *   <li><tt>success</tt>: Not required, specifies the listener to invoke on form 
submission.</li>
+  *   <li><tt>success</tt>: Not required, specifies the listener to invoke on
+  *      form submission.</li>
-  *   <li><tt>cancel</tt>: Not required, specifies the listener to invoke on form 
cancellation.</li>
+  *   <li><tt>cancel</tt>: Not required, specifies the listener to invoke on
+  *      form cancellation.</li>
-  *   <li><tt>refresh</tt>: Not required, specifies the listener to invoke on form 
refresh.</li>
+  *   <li><tt>refresh</tt>: Not required, specifies the listener to invoke on
+  *      form refresh.</li>
+  *   <li><tt>delegate</tt>: Not required, specifies the validation delegate to
+  *      use on the form.</li>
+  *   <li>And all the rest of the <tt>Form</tt> parameters, including
+  *      <tt>method</tt>, <tt>listener</tt>, <tt>stateful</tt>, 
<tt>direct</tt>,
+  *      <tt>clientValidationEnabled</tt>, <tt>focus</tt>, <tt>scheme</tt> and
+  *      <tt>port</tt>. See the <tt>Form</tt> component's documentation for
+  *      more details.
   * </ul>
   *
-  * <p>The generated HTML is a form containing a two-column table, unless this 
component
+  * <p>The generated HTML is a form containing a two-column table, unless this
-  * is inside an external Form component, in which case no extraneous form is 
generated. The table's
+  * component is inside an external Form component, in which case no extraneous
-  * left column contains the field labels and the right column contains the 
data entry fields.
+  * form is generated. The table's left column contains the field labels and 
the
+  * right column contains the data entry fields. The bottom row spans both
-  * The bottom row spans both columns and contains the save button (if the 
<tt>save</tt> parameter
+  * columns and contains the save button (if the <tt>save</tt> parameter was
-  * was specified), the cancel button (if the <tt>cancel</tt> parameter was 
specified), the
+  * specified), the cancel button (if the <tt>cancel</tt> parameter was
-  * refresh button (if the <tt>refresh</tt> parameter was specified) and the 
delete button (if
-  * the <tt>delete</tt> parameter was specified).</p>
+  * specified), the refresh button (if the <tt>refresh</tt> parameter was
+  * specified) and the delete button (if the <tt>delete</tt> parameter was
+  * specified).</p>
   *
-  * <p>The table can be styled using CSS: the table's CSS class is 
<tt>beanFormTable</tt>,
+  * <p>The table can be styled using CSS: the table's CSS class is
+  * <tt>beanFormTable</tt>, the left column's CSS class is
-  * the left column's CSS class is <tt>beanFormLeftColumn</tt>, the right 
column's CSS class
+  * <tt>beanFormLeftColumn</tt>, the right column's CSS class is
-  * is <tt>beanFormRightColumn</tt>, and the bottom column that contains the 
buttons has
+  * <tt>beanFormRightColumn</tt>, and the bottom column that contains the
-  * the CSS class <tt>beanFormButtonColumn</tt>.</p>
+  * buttons has the CSS class <tt>beanFormButtonColumn</tt>.</p>
   *
-  * <p>If you need to customize any of the input fields, you can do so by adding a 
<tt>Block</tt>
+  * <p>If you need to customize any of the input fields, you can do so by 
adding
+  * a <tt>Block</tt> component to your page (with the id
-  * component to your page (with the id <tt>[propertyName]BeanFieldBlock</tt>) 
that contains any
+  * <tt>[propertyName]BeanFieldBlock</tt>) that contains any
-  * <tt>IFormComponent</tt> (with the id <tt>[propertyName]BeanField</tt>).</p>
+  * <tt>IFormComponent</tt> (with the id <tt>[propertyName]BeanField</tt>).
+  * Doing this will allow you to edit properties that are considered
+  * non-editable by default (ie, not a string/boolean/number/date).</p>
+  *
+  * <p>In order to use validation, specify the <tt>delegate</tt> parameter
+  * (unless you have already specified it in an external <tt>Form</tt> 
component
+  * that contains this component) and add standard validation lists to the
+  * <tt>properties</tt> parameter, in between squiggly brackets (<tt>{}</tt>).
+  * See below for an example.</p>
   *
   * <p>Usage examples:</p>
   * <ul>
-  *   <li>Minimal: <tt>&lt;span jwcid="@BeanForm" bean="ognl:pojo" 
success="ognl:listeners.save"/&gt;</tt></li>
-  *   <li>Normal: <tt>&lt;span jwcid="@BeanForm" bean="ognl:pojo" 
properties="ognl:'name,email,comment'"
-  *      success="ognl:listeners.save" cancel="ognl:listeners.cancel" 
refresh="ognl:listeners.refresh" /&gt;</tt></li>
+  *   <li>Minimal: <tt>&lt;span jwcid="@BeanForm" bean="ognl:pojo"
+  *      save="ognl:listeners.save"/&gt;</tt></li>
+  *   <li>More: <tt>&lt;span jwcid="@BeanForm" bean="ognl:pojo"
+  *      properties="ognl:'name,email,comment'" save="ognl:listeners.save"
+  *      cancel="ognl:listeners.cancel"
+  *      delete="ognl:listeners.delete"
+  *      refresh="ognl:listeners.refresh" /&gt;</tt></li>
-  *   <li>To edit the <tt>comment</tt> property in a text area you would add the 
following to your page:<br>
+  *   <li>To edit the <tt>comment</tt> property in a text area you would add 
the
+  *      following to your page:<br>
   *      <tt>&lt;div jwcid="[EMAIL PROTECTED]"&gt;</tt><br>
-  *      <tt>&lt;input jwcid="[EMAIL PROTECTED]" value="ognl:pojo.comment" 
displayName="message:comment"/&gt;</tt><br>
+  *      <tt>&lt;input jwcid="[EMAIL PROTECTED]"
+  *         value="ognl:pojo.comment"
+  *         displayName="message:comment"/&gt;</tt><br>
   *      <tt>&lt;/div&gt;</tt><br>
-  *   </tt></li>
+  *      </tt></li>
+  *   <li>To make <tt>name</tt> and <tt>email</tt> required, and check that
+  *      <tt>email</tt> is actually an email:
+  *      <tt>&lt;span jwcid="@BeanForm" bean="ognl:pojo"
+  *      properties="ognl:'name{required},email{required,email},comment'"
+  *      save="ognl:listeners.save" clientValidationEnabled="ognl:true"
+  *      delegate="ognl:beans.validationDelegate"/&gt;</tt></li>
   * </ul>
   *
-  * <p>Possible enhancements:</p>
-  *
-  * <ul>
-  *   <li>Expose all the parameters exposed by the <tt>Form</tt> 
component.</li>
-  *   <li>Add validation, perhaps within the <tt>properties</tt> parameter 
(ie, if you have
-  *      <tt>properties</tt> set to <tt>"name,email,comment"</tt> and you want to make 
<tt>name</tt>
-  *      and <tt>email</tt> required, you might set <tt>properties</tt> to
-  *      <tt>"name{required},email{required,email},comment"</tt>).</li>
-  * </ul>
-  *
   * @author Daniel Gredler
-  * @version 1.1
+  * @version 1.2
   */
  public abstract class BeanForm extends BaseComponent {

        private final static Logger LOG = Logger.getLogger( BeanForm.class );
+       private final static Pattern PROPERTIES_PATTERN = Pattern.compile( 
"\\s*(\\w+)\\s*(?:\\{\\s*(.+?)\\s*\\}\\s*)?,?" );
        private final static String CUSTOM_FIELD_BLOCK_SUFFIX = 
"BeanFieldBlock";
        private final static String CUSTOM_FIELD_SUFFIX = "BeanField";

        @InjectObject( "infrastructure:requestCycle" )
        public abstract IRequestCycle getCycle();

+       @InjectObject( 
"service:tapestry.form.validator.ValidatorsBindingFactory" )
+       public abstract BindingFactory getValidatorsBindingFactory();
+
        public abstract Object getBean();
        public abstract void setBean( Object bean );

@@ -189, +244 @@

        public abstract void setProperties( String properties );

        public List<BeanProperty> getBeanProperties() {
+               List<BeanProperty> properties = new ArrayList<BeanProperty>();
                Object bean = this.getBean();
                BeanInfo info = this.getBeanInfo();
-               List<String> names = this.getEditablePropertyNames();
                PropertyDescriptor[] descriptors = 
info.getPropertyDescriptors();
-               List<BeanProperty> properties = new ArrayList<BeanProperty>();
                for( PropertyDescriptor descriptor : descriptors ) {
                        BeanProperty property = new BeanProperty( descriptor );
-                       String name = property.getName();
-                       if( names == null || names.contains( name ) ) {
-                               if( property.isEditableType() ) {
+                       String validators = this.getValidators( property );
+                       property.setValidators( validators );
+                       if( this.isIncluded( property ) ) {
+                               if( property.isEditableType() || 
this.hasCustomField( property ) ) {
                                        properties.add( property );
                                }
-                               else if( names != null ){
-                                       LOG.warn( "Explicitly included property '" + name 
+ "' cannot be edited because it is not a string, boolean, number or date." );
+                               else if( this.hasExplicitProperties() ) {
+                                       LOG.warn( "Explicitly included bean property '" + 
property.getName() + "' is not a " +
+                                               "string/boolean/number/date, and a 
custom field was not specified for it." );
                                }
                        }
                }
-               properties = this.reorderProperties( properties, names );
+               properties = this.reorderProperties( properties );
                if( LOG.isDebugEnabled() ) {
                        LOG.debug( "Found " + properties.size() + " editable properties for 
bean " + bean + ": " + properties );
                }
@@ -221, +277 @@

                catch( ApplicationRuntimeException e ) {
                        return false;
                }
+       }
+
+       public List getValidatorList( BeanProperty property, IComponent 
component ) {
+               String name = property.getName();
+               String desc = "dynamic validators binding for bean property " + 
name;
+               String expression = property.getValidators();
+               Location location = component.getLocation();
+               BindingFactory factory = this.getValidatorsBindingFactory();
+               ValidatorsBinding binding = (ValidatorsBinding) 
factory.createBinding( component, desc, expression, location );
+               List validators = (List) binding.getObject();
+               if( LOG.isDebugEnabled() ) {
+                       LOG.debug( "Bean property '" + name + "' has " + 
validators.size() + " validators: " + validators );
+               }
+               return validators;
        }

        public boolean hasCustomField( BeanProperty property ) {
@@ -273, +343 @@

                return info;
        }

-       private List<String> getEditablePropertyNames() {
+       private List<String> explicitPropertyNames;
+       private Map<String, String> explicitPropertyValidators;
+
+       private String getValidators( BeanProperty property ) {
+               this.initExplicitProperties();
+               if( this.explicitPropertyValidators == null ) return null;
+               return this.explicitPropertyValidators.get( property.getName() 
);
-               String s = this.getProperties();
-               List<String> names;
-               if( s != null ) {
-                       String[] array = s.split( "," );
-                       for( int i = 0; i < array.length; i++ ) {
-                               array[ i ] = array[ i ].trim();
-                       }
-                       names = Arrays.asList( array );
-               }
+       }
-               else {
-                       names = null;
+
+       private boolean isIncluded( BeanProperty property ) {
+               this.initExplicitProperties();
+               if( this.explicitPropertyNames == null ) return true;
+               return this.explicitPropertyNames.contains( property.getName() 
);
-               }
+       }
-               return names;
-       }

-       private List<BeanProperty> reorderProperties( List<BeanProperty> properties, 
List<String> orderedNames ) {
+       private List<BeanProperty> reorderProperties( List<BeanProperty> 
properties ) {
+               this.initExplicitProperties();
-               if( orderedNames == null ) return properties;
+               if( this.explicitPropertyNames == null ) return properties;
                List<BeanProperty> orderedProperties = new 
ArrayList<BeanProperty>( properties.size() );
-               for( String name : orderedNames ) {
+               for( String name : this.explicitPropertyNames ) {
                        for( BeanProperty property : properties ) {
                                if( property.getName().equals( name ) ) {
                                        orderedProperties.add( property );
@@ -300, +370 @@

                        }
                }
                return orderedProperties;
+       }
+
+       private boolean hasExplicitProperties() {
+               this.initExplicitProperties();
+               return ( this.explicitPropertyNames != null );
+       }
+
+       private synchronized void initExplicitProperties() {
+               if( this.explicitPropertyNames != null ) return;
+               String s = this.getProperties();
+               if( s == null ) return;
+               this.explicitPropertyNames = new ArrayList<String>();
+               this.explicitPropertyValidators = new HashMap<String, String>();
+               Matcher m = PROPERTIES_PATTERN.matcher( s );
+               while( m.find() ) {
+                       String name = m.group( 1 );
+                       String validators = m.group( 2 );
+                       this.explicitPropertyNames.add( name );
+                       this.explicitPropertyValidators.put( name, validators );
+               }
        }

        /**
@@ -324, +414 @@

                private static final String DATE = Date.class.getName();

                private String name;
+               private String validators;
                private boolean readOnly;
                private String typeName;

                public BeanProperty( PropertyDescriptor descriptor ) {
                        this.name = descriptor.getName();
+                       this.validators = null;
                        this.readOnly = descriptor.getWriteMethod() == null;
                        this.typeName = descriptor.getPropertyType().getName();
                }

                public String getName() {
                        return this.name;
+               }
+
+               public String getValidators() {
+                       return this.validators;
+               }
+
+               public void setValidators( String validators ) {
+                       this.validators = validators;
                }

                public boolean isReadOnly() {
@@ -370, +470 @@


                @Override
                public String toString() {
-                       return this.getName();
+                       return this.name + ( this.validators != null ? "{" + this.validators + 
"}" : "" );
                }

        }
@@ -395, +495 @@

        <parameter name="save" required="false"/>
        <parameter name="delete" required="false"/>

+       <parameter name="method" required="false"/>
        <parameter name="success" required="false"/>
        <parameter name="cancel" required="false"/>
        <parameter name="refresh" required="false"/>
+       <parameter name="listener" required="false"/>
+       <parameter name="stateful" required="false"/>
+       <parameter name="direct" required="false"/>
+       <parameter name="delegate" required="false"/>
+       <parameter name="clientValidationEnabled" required="false"/>
+       <parameter name="focus" required="false"/>
+       <parameter name="scheme" required="false"/>
+       <parameter name="port" required="false"/>

        <property name="beanProperty"/>

@@ -415, +524 @@

        </component>

        <component id="beanForm" type="Form">
+               <binding name="method" value="method"/>
                <binding name="success" value="success"/>
                <binding name="cancel" value="cancel"/>
                <binding name="refresh" value="refresh"/>
+               <binding name="listener" value="listener"/>
+               <binding name="stateful" value="stateful"/>
+               <binding name="direct" value="direct"/>
+               <binding name="delegate" value="delegate"/>
+               <binding name="clientValidationEnabled" 
value="clientValidationEnabled"/>
+               <binding name="focus" value="focus"/>
+               <binding name="scheme" value="scheme"/>
+               <binding name="port" value="port"/>
        </component>
        <component id="beanPropertyRow" type="For">
                <binding name="source" value="beanProperties"/>
@@ -457, +575 @@

                <binding name="value" value="(beanProperty.name)(bean)"/>
                <binding name="disabled" value="beanProperty.readOnly"/>
                <binding name="displayName" 
value="getMessage(beanProperty.name)"/>
+               <binding name="validators" 
value="getValidatorList(beanProperty,#this)"/>
        </component>

        <component id="beanPropertyLabel_Checkbox" type="FieldLabel">
@@ -466, +585 @@

                <binding name="value" value="(beanProperty.name)(bean)"/>
                <binding name="disabled" value="beanProperty.readOnly"/>
                <binding name="displayName" 
value="getMessage(beanProperty.name)"/>
+               <binding name="validators" 
value="getValidatorList(beanProperty,#this)"/>
        </component>

        <component id="beanPropertyLabel_Number" type="FieldLabel">
@@ -475, +595 @@

                <binding name="value" value="(beanProperty.name)(bean)"/>
                <binding name="disabled" value="beanProperty.readOnly"/>
                <binding name="displayName" 
value="getMessage(beanProperty.name)"/>
+               <binding name="validators" 
value="getValidatorList(beanProperty,#this)"/>
        </component>

        <component id="beanPropertyLabel_Date" type="FieldLabel">
@@ -484, +605 @@

                <binding name="value" value="(beanProperty.name)(bean)"/>
                <binding name="disabled" value="beanProperty.readOnly"/>
                <binding name="displayName" 
value="getMessage(beanProperty.name)"/>
+               <binding name="validators" 
value="getValidatorList(beanProperty,#this)"/>
        </component>

        <component id="hasSave" type="If">

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




--
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to