You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2009/12/11 07:57:00 UTC
svn commit: r889518 -
/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
Author: hlship
Date: Fri Dec 11 06:56:59 2009
New Revision: 889518
URL: http://svn.apache.org/viewvc?rev=889518&view=rev
Log:
TAP5-796: Form component generates invalid xHtml: there should not be the "name" attribute
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java?rev=889518&r1=889517&r2=889518&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java Fri Dec 11 06:56:59 2009
@@ -41,81 +41,103 @@
import java.io.ObjectInputStream;
/**
- * An HTML form, which will enclose other components to render out the various types of fields.
+ * An HTML form, which will enclose other components to render out the various
+ * types of fields.
* <p/>
- * A Form emits many notification events. When it renders, it fires a {@link org.apache.tapestry5.EventConstants#PREPARE_FOR_RENDER}
- * notification, followed by a {@link org.apache.tapestry5.EventConstants#PREPARE} notification.
+ * A Form emits many notification events. When it renders, it fires a
+ * {@link org.apache.tapestry5.EventConstants#PREPARE_FOR_RENDER} notification,
+ * followed by a {@link org.apache.tapestry5.EventConstants#PREPARE}
+ * notification.
* <p/>
- * When the form is submitted, the component emits several notifications: first a {@link
- * org.apache.tapestry5.EventConstants#PREPARE_FOR_SUBMIT}, then a {@link org.apache.tapestry5.EventConstants#PREPARE}:
- * these allow the page to update its state as necessary to prepare for the form submission, then (after components
- * enclosed by the form have operated), a {@link org.apache.tapestry5.EventConstants#VALIDATE_FORM} event is emitted, to
- * allow for cross-form validation. After that, either a {@link org.apache.tapestry5.EventConstants#SUCCESS} OR {@link
- * org.apache.tapestry5.EventConstants#FAILURE} event (depending on whether the {@link ValidationTracker} has recorded
- * any errors). Lastly, a {@link org.apache.tapestry5.EventConstants#SUBMIT} event, for any listeners that care only
- * about form submission, regardless of success or failure.
+ * When the form is submitted, the component emits several notifications: first
+ * a {@link org.apache.tapestry5.EventConstants#PREPARE_FOR_SUBMIT}, then a
+ * {@link org.apache.tapestry5.EventConstants#PREPARE}: these allow the page to
+ * update its state as necessary to prepare for the form submission, then (after
+ * components enclosed by the form have operated), a
+ * {@link org.apache.tapestry5.EventConstants#VALIDATE_FORM} event is emitted,
+ * to allow for cross-form validation. After that, either a
+ * {@link org.apache.tapestry5.EventConstants#SUCCESS} OR
+ * {@link org.apache.tapestry5.EventConstants#FAILURE} event (depending on
+ * whether the {@link ValidationTracker} has recorded any errors). Lastly, a
+ * {@link org.apache.tapestry5.EventConstants#SUBMIT} event, for any listeners
+ * that care only about form submission, regardless of success or failure.
* <p/>
- * For all of these notifications, the event context is derived from the <strong>context</strong> parameter. This
- * context is encoded into the form's action URI (the parameter is not read when the form is submitted, instead the
+ * For all of these notifications, the event context is derived from the
+ * <strong>context</strong> parameter. This context is encoded into the form's
+ * action URI (the parameter is not read when the form is submitted, instead the
* values encoded into the form are used).
*/
-@Events({ EventConstants.PREPARE_FOR_RENDER, EventConstants.PREPARE, EventConstants.PREPARE_FOR_SUBMIT,
- EventConstants.VALIDATE_FORM,
- EventConstants.SUBMIT, EventConstants.FAILURE, EventConstants.SUCCESS })
+@Events(
+{ EventConstants.PREPARE_FOR_RENDER, EventConstants.PREPARE, EventConstants.PREPARE_FOR_SUBMIT,
+ EventConstants.VALIDATE_FORM, EventConstants.SUBMIT, EventConstants.FAILURE,
+ EventConstants.SUCCESS })
public class Form implements ClientElement, FormValidationControl
{
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String PREPARE_FOR_RENDER = EventConstants.PREPARE_FOR_RENDER;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String PREPARE_FOR_SUBMIT = EventConstants.PREPARE_FOR_SUBMIT;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String PREPARE = EventConstants.PREPARE;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String SUBMIT = EventConstants.SUBMIT;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String VALIDATE_FORM = EventConstants.VALIDATE_FORM;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String SUCCESS = EventConstants.SUCCESS;
/**
- * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants} instead.
+ * @deprecated Use constant from {@link org.apache.tapestry5.EventConstants}
+ * instead.
*/
public static final String FAILURE = EventConstants.FAILURE;
/**
- * Query parameter name storing form data (the serialized commands needed to process a form submission).
+ * Query parameter name storing form data (the serialized commands needed to
+ * process a form submission).
*/
public static final String FORM_DATA = "t:formdata";
/**
- * The context for the link (optional parameter). This list of values will be converted into strings and included in
- * the URI. The strings will be coerced back to whatever their values are and made available to event handler
+ * The context for the link (optional parameter). This list of values will
+ * be converted into strings and included in
+ * the URI. The strings will be coerced back to whatever their values are
+ * and made available to event handler
* methods.
*/
@Parameter
private Object[] context;
/**
- * The object which will record user input and validation errors. The object must be persistent between requests
- * (since the form submission and validation occurs in an component event request and the subsequent render occurs
- * in a render request). The default is a persistent property of the Form component and this is sufficient for
+ * The object which will record user input and validation errors. The object
+ * must be persistent between requests
+ * (since the form submission and validation occurs in an component event
+ * request and the subsequent render occurs
+ * in a render request). The default is a persistent property of the Form
+ * component and this is sufficient for
* nearly all purposes (except when a Form is rendered inside a loop).
*/
@Parameter("defaultTracker")
@@ -126,42 +148,52 @@
private boolean clientLogicDefaultEnabled;
/**
- * If true (the default) then client validation is enabled for the form, and the default set of JavaScript libraries
- * (Prototype, Scriptaculous and the Tapestry library) will be added to the rendered page, and the form will
- * register itself for validation. This may be turned off when client validation is not desired; for example, when
+ * If true (the default) then client validation is enabled for the form, and
+ * the default set of JavaScript libraries
+ * (Prototype, Scriptaculous and the Tapestry library) will be added to the
+ * rendered page, and the form will
+ * register itself for validation. This may be turned off when client
+ * validation is not desired; for example, when
* many validations are used that do not operate on the client side at all.
*/
@Parameter
private boolean clientValidation = clientLogicDefaultEnabled;
/**
- * If true (the default), then the JavaScript will be added to position the cursor into the form. The field to
- * receive focus is the first rendered field that is in error, or required, or present (in that order of priority).
- *
+ * If true (the default), then the JavaScript will be added to position the
+ * cursor into the form. The field to
+ * receive focus is the first rendered field that is in error, or required,
+ * or present (in that order of priority).
+ *
* @see SymbolConstants#FORM_CLIENT_LOGIC_ENABLED
*/
@Parameter
private boolean autofocus = clientLogicDefaultEnabled;
/**
- * Binding the zone parameter will cause the form submission to be handled as an Ajax request that updates the
- * indicated zone. Often a Form will update the same zone that contains it.
+ * Binding the zone parameter will cause the form submission to be handled
+ * as an Ajax request that updates the
+ * indicated zone. Often a Form will update the same zone that contains it.
*/
@Parameter(defaultPrefix = BindingConstants.LITERAL)
private String zone;
/**
- * Prefix value used when searching for validation messages and constraints. The default is the Form component's
- * id. This is overriden by {@link org.apache.tapestry5.corelib.components.BeanEditForm}.
- *
+ * Prefix value used when searching for validation messages and constraints.
+ * The default is the Form component's
+ * id. This is overriden by
+ * {@link org.apache.tapestry5.corelib.components.BeanEditForm}.
+ *
* @see org.apache.tapestry5.services.FormSupport#getFormValidationId()
*/
@Parameter
private String validationId;
-
+
/**
- * Object to validate during the form submission process. The value of this parameter is pushed as a
- * {@link org.apache.tapestry5.services.BeanValidationContext} into the environment. This parameter should
+ * Object to validate during the form submission process. The value of this
+ * parameter is pushed as a
+ * {@link org.apache.tapestry5.services.BeanValidationContext} into the
+ * environment. This parameter should
* only be used in combination with the Bean Validation Library.
*/
@Parameter
@@ -197,7 +229,8 @@
private Element div;
- // Collects a stream of component actions. Each action goes in as a UTF string (the component
+ // Collects a stream of component actions. Each action goes in as a UTF
+ // string (the component
// component id), followed by a ComponentAction
private ComponentActionSink actionSink;
@@ -223,7 +256,7 @@
{
return resources.getId();
}
-
+
Object defaultValidate()
{
return resources.getContainer();
@@ -231,7 +264,8 @@
public ValidationTracker getDefaultTracker()
{
- if (defaultTracker == null) defaultTracker = new ValidationTrackerImpl();
+ if (defaultTracker == null)
+ defaultTracker = new ValidationTrackerImpl();
return defaultTracker;
}
@@ -259,35 +293,35 @@
formSupport = createRenderTimeFormSupport(name, actionSink, new IdAllocator());
- if (zone != null) clientBehaviorSupport.linkZone(name, zone, link);
+ if (zone != null)
+ clientBehaviorSupport.linkZone(name, zone, link);
- // TODO: Forms should not allow to nest. Perhaps a set() method instead of a push() method
- // for this kind of check?
+ // TODO: Forms should not allow to nest. Perhaps a set() method instead
+ // of a push() method
+ // for this kind of check?
environment.push(FormSupport.class, formSupport);
environment.push(ValidationTracker.class, tracker);
if (autofocus)
{
- ValidationDecorator autofocusDecorator = new AutofocusValidationDecorator(environment.peek(
- ValidationDecorator.class), tracker, renderSupport);
+ ValidationDecorator autofocusDecorator = new AutofocusValidationDecorator(environment
+ .peek(ValidationDecorator.class), tracker, renderSupport);
environment.push(ValidationDecorator.class, autofocusDecorator);
}
- // Now that the environment is setup, inform the component or other listeners that the form
- // is about to render.
+ // Now that the environment is setup, inform the component or other
+ // listeners that the form
+ // is about to render.
resources.triggerEvent(EventConstants.PREPARE_FOR_RENDER, context, null);
resources.triggerEvent(EventConstants.PREPARE, context, null);
- // Save the form element for later, in case we want to write an encoding type attribute.
+ // Save the form element for later, in case we want to write an encoding
+ // type attribute.
- form = writer.element("form",
- "name", name,
- "id", name,
- "method", "post",
- "action", link);
+ form = writer.element("form", "id", name, "method", "post", "action", link);
if ((zone != null || clientValidation) && !request.isXHR())
writer.attributes("onsubmit", MarkupConstants.WAIT_FOR_PAGE);
@@ -300,10 +334,7 @@
{
String value = link.getParameterValue(parameterName);
- writer.element("input",
- "type", "hidden",
- "name", parameterName,
- "value", value);
+ writer.element("input", "type", "hidden", "name", parameterName, "value", value);
writer.end();
}
@@ -313,19 +344,27 @@
}
/**
- * Creates an {@link org.apache.tapestry5.corelib.internal.InternalFormSupport} for this Form. This method is used
+ * Creates an
+ * {@link org.apache.tapestry5.corelib.internal.InternalFormSupport} for
+ * this Form. This method is used
* by {@link org.apache.tapestry5.corelib.components.FormInjector}.
- *
- * @param name the client-side name and client id for the rendered form element
- * @param actionSink used to collect component actions that will, ultimately, be written as the t:formdata hidden
- * field
- * @param allocator used to allocate unique ids
+ *
+ * @param name
+ * the client-side name and client id for the rendered form
+ * element
+ * @param actionSink
+ * used to collect component actions that will, ultimately, be
+ * written as the t:formdata hidden
+ * field
+ * @param allocator
+ * used to allocate unique ids
* @return form support object
*/
- InternalFormSupport createRenderTimeFormSupport(String name, ComponentActionSink actionSink, IdAllocator allocator)
+ InternalFormSupport createRenderTimeFormSupport(String name, ComponentActionSink actionSink,
+ IdAllocator allocator)
{
return new FormSupportImpl(resources, name, actionSink, clientBehaviorSupport,
- clientValidation, allocator, validationId);
+ clientValidation, allocator, validationId);
}
void afterRender(MarkupWriter writer)
@@ -336,14 +375,13 @@
String encodingType = formSupport.getEncodingType();
- if (encodingType != null) form.forceAttributes("enctype", encodingType);
+ if (encodingType != null)
+ form.forceAttributes("enctype", encodingType);
writer.end(); // form
- div.element("input",
- "type", "hidden",
- "name", FORM_DATA,
- "value", actionSink.getClientData());
+ div.element("input", "type", "hidden", "name", FORM_DATA, "value", actionSink
+ .getClientData());
if (autofocus)
environment.pop(ValidationDecorator.class);
@@ -358,7 +396,8 @@
environment.pop(ValidationTracker.class);
}
- @SuppressWarnings({ "unchecked", "InfiniteLoopStatement" })
+ @SuppressWarnings(
+ { "unchecked", "InfiniteLoopStatement" })
@Log
Object onAction(EventContext context) throws IOException
{
@@ -368,12 +407,14 @@
environment.push(ValidationTracker.class, tracker);
environment.push(FormSupport.class, formSupport);
- environment.push(BeanValidationContext.class, new BeanValidationContext(){
+ environment.push(BeanValidationContext.class, new BeanValidationContext()
+ {
public Object getObject()
{
return validate;
- }});
+ }
+ });
Heartbeat heartbeat = new HeartbeatImpl();
@@ -388,11 +429,13 @@
resources.triggerContextEvent(EventConstants.PREPARE_FOR_SUBMIT, context, callback);
- if (callback.isAborted()) return true;
+ if (callback.isAborted())
+ return true;
resources.triggerContextEvent(EventConstants.PREPARE, context, callback);
- if (callback.isAborted()) return true;
+ if (callback.isAborted())
+ return true;
executeStoredActions();
@@ -402,24 +445,29 @@
fireValidateFormEvent(context, callback);
- if (callback.isAborted()) return true;
+ if (callback.isAborted())
+ return true;
- // Let the listeners know about overall success or failure. Most listeners fall into
+ // Let the listeners know about overall success or failure. Most
+ // listeners fall into
// one of those two camps.
// If the tracker has no errors, then clear it of any input values
// as well, so that the next page render will be "clean" and show
- // true persistent data, not value from the previous form submission.
+ // true persistent data, not value from the previous form
+ // submission.
if (!tracker.getHasErrors())
tracker.clear();
- resources.triggerContextEvent(tracker.getHasErrors() ? EventConstants.FAILURE : EventConstants.SUCCESS,
- context, callback);
+ resources.triggerContextEvent(tracker.getHasErrors() ? EventConstants.FAILURE
+ : EventConstants.SUCCESS, context, callback);
- // Lastly, tell anyone whose interested that the form is completely submitted.
+ // Lastly, tell anyone whose interested that the form is completely
+ // submitted.
- if (callback.isAborted()) return true;
+ if (callback.isAborted())
+ return true;
resources.triggerContextEvent(EventConstants.SUBMIT, context, callback);
@@ -430,17 +478,20 @@
environment.pop(Heartbeat.class);
environment.pop(FormSupport.class);
- // This forces an update that feeds through the system and gets the updated
- // state of the tracker (if using the Form's defaultTracker property, which is flash persisted)
+ // This forces an update that feeds through the system and gets the
+ // updated
+ // state of the tracker (if using the Form's defaultTracker
+ // property, which is flash persisted)
// stored back into the session.
tracker = environment.pop(ValidationTracker.class);
-
+
environment.pop(BeanValidationContext.class);
}
}
- private void fireValidateFormEvent(EventContext context, ComponentResultProcessorWrapper callback)
+ private void fireValidateFormEvent(EventContext context,
+ ComponentResultProcessorWrapper callback)
{
try
{
@@ -461,7 +512,8 @@
}
/**
- * Pulls the stored actions out of the request, converts them from MIME stream back to object stream and then
+ * Pulls the stored actions out of the request, converts them from MIME
+ * stream back to object stream and then
* objects, and executes them.
*/
private void executeStoredActions()
@@ -471,11 +523,13 @@
if (!request.getMethod().equals("POST") || values == null)
throw new RuntimeException(messages.format("invalid-request", FORM_DATA));
- // Due to Ajax (FormInjector) there may be multiple values here, so handle each one individually.
+ // Due to Ajax (FormInjector) there may be multiple values here, so
+ // handle each one individually.
for (String clientEncodedActions : values)
{
- if (InternalUtils.isBlank(clientEncodedActions)) continue;
+ if (InternalUtils.isBlank(clientEncodedActions))
+ continue;
logger.debug("Processing actions: {}", clientEncodedActions);
@@ -507,7 +561,8 @@
}
catch (Exception ex)
{
- Location location = component == null ? null : component.getComponentResources().getLocation();
+ Location location = component == null ? null : component.getComponentResources()
+ .getLocation();
throw new TapestryException(ex.getMessage(), location, ex);
}