Repository: tapestry-5 Updated Branches: refs/heads/master 246e67709 -> 94b18f6b7
TAP5-2603: Create HTML5-based date form field component Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/94b18f6b Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/94b18f6b Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/94b18f6b Branch: refs/heads/master Commit: 94b18f6b74e3c493515157909fad932f48caec1a Parents: 246e677 Author: Thiago H. de Paula Figueiredo <[email protected]> Authored: Sat Dec 8 12:23:16 2018 -0200 Committer: Thiago H. de Paula Figueiredo <[email protected]> Committed: Sat Dec 8 12:24:21 2018 -0200 ---------------------------------------------------------------------- .../corelib/components/Html5DateField.java | 177 +++++++++++++++++++ .../src/test/app1/Html5DateFieldDemo.tml | 47 +++++ .../app1/pages/Html5DateFieldDemo.java | 71 ++++++++ .../tapestry5/integration/app1/pages/Index.java | 4 +- 4 files changed, 298 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/94b18f6b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Html5DateField.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Html5DateField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Html5DateField.java new file mode 100644 index 0000000..21cfabe --- /dev/null +++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Html5DateField.java @@ -0,0 +1,177 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.corelib.components; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.tapestry5.Binding; +import org.apache.tapestry5.BindingConstants; +import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.EventConstants; +import org.apache.tapestry5.FieldValidator; +import org.apache.tapestry5.MarkupWriter; +import org.apache.tapestry5.ValidationException; +import org.apache.tapestry5.annotations.Events; +import org.apache.tapestry5.annotations.Parameter; +import org.apache.tapestry5.corelib.base.AbstractField; +import org.apache.tapestry5.ioc.Messages; +import org.apache.tapestry5.ioc.internal.util.InternalUtils; +import org.apache.tapestry5.services.ComponentDefaultProvider; + +/** + * A component used to collect a provided date from the user using the native HTML5 date picker + * (<input type="date">) + * @tapestrydoc + * @see Form + * @see TextField + */ +@Events(EventConstants.VALIDATE) +public class Html5DateField extends AbstractField +{ + + final private static String DATE_FORMAT = "yyyy-MM-dd"; + + /** + * The value parameter of a DateField must be a {@link java.util.Date}. + */ + @Parameter(required = true, principal = true, autoconnect = true) + private Date value; + + /** + * The object that will perform input validation (which occurs after translation). The translate binding prefix is + * generally used to provide this object in a declarative fashion. + */ + @Parameter(defaultPrefix = BindingConstants.VALIDATE) + private FieldValidator<Object> validate; + + /** + * Used to override the component's message catalog. + * + * @since 5.2.0.0 + * @deprecated Since 5.4; override the global message key "core-date-value-not-parsable" instead (see {@link org.apache.tapestry5.services.messages.ComponentMessagesSource}) + */ + @Parameter("componentResources.messages") + private Messages messages; + + /** + * Computes a default value for the "validate" parameter using {@link ComponentDefaultProvider}. + */ + final Binding defaultValidate() + { + return defaultProvider.defaultValidatorBinding("value", resources); + } + + void beginRender(MarkupWriter writer) + { + String value = validationTracker.getInput(this); + + if (value == null) + { + value = formatCurrentValue(); + } + + String clientId = getClientId(); + + writer.element("input", + + "type", "date", + + "class", cssClass, + + "name", getControlName(), + + "id", clientId, + + "value", value); + + writeDisabled(writer); + + putPropertyNameIntoBeanValidationContext("value"); + + validate.render(writer); + + removePropertyNameFromBeanValidationContext(); + + resources.renderInformalParameters(writer); + + decorateInsideField(); + + writer.end(); // input + + } + + private void writeDisabled(MarkupWriter writer) + { + if (isDisabled()) + writer.attributes("disabled", "disabled"); + } + + private String formatCurrentValue() + { + if (value == null) + return ""; + + return getDateFormat().format(value); + } + + private DateFormat getDateFormat() { + return new SimpleDateFormat(DATE_FORMAT); + } + + @Override + protected void processSubmission(String controlName) + { + String value = request.getParameter(controlName); + + validationTracker.recordInput(this, value); + + Date parsedValue = null; + + try + { + if (InternalUtils.isNonBlank(value)) + parsedValue = getDateFormat().parse(value); + } catch (ParseException ex) + { + validationTracker.recordError(this, messages.format("core-date-value-not-parseable", value)); + return; + } + + putPropertyNameIntoBeanValidationContext("value"); + try + { + fieldValidationSupport.validate(parsedValue, resources, validate); + + this.value = parsedValue; + } catch (ValidationException ex) + { + validationTracker.recordError(this, ex.getMessage()); + } + + removePropertyNameFromBeanValidationContext(); + } + + void injectResources(ComponentResources resources) + { + this.resources = resources; + } + + @Override + public boolean isRequired() + { + return validate.isRequired(); + } +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/94b18f6b/tapestry-core/src/test/app1/Html5DateFieldDemo.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/app1/Html5DateFieldDemo.tml b/tapestry-core/src/test/app1/Html5DateFieldDemo.tml new file mode 100644 index 0000000..f926f7f --- /dev/null +++ b/tapestry-core/src/test/app1/Html5DateFieldDemo.tml @@ -0,0 +1,47 @@ +<html t:type="Border" + xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"> + +<h1>DateField Demo</h1> + +<t:form> + <t:errors/> + + <div class="field-group x-birthday"> + <t:label for="birthday"/> + <t:html5datefield t:id="birthday"/> + </div> + + <div class="field-group x-impact"> + <t:label for="asteroidImpact"/> + <t:html5datefield t:id="asteroidImpact"/> + </div> + + <input type="submit" value="Go" class="btn btn-primary"/> + +</t:form> + +<div class="btn-group"> + + <t:actionlink class="btn btn-default" t:id="clear">clear</t:actionlink> + <t:actionlink class="btn btn-default" t:id="english">english</t:actionlink> + <t:actionlink class="btn btn-default" t:id="french">french</t:actionlink> + +</div> + +<hr/> + +<dl> + <dt>Birthday</dt> + <dd id="birthday-output"> + <t:output value="birthday" format="dateFormat"/> + </dd> + <dt>Impact</dt> + <dd id="impact-output"> + <t:output value="asteroidImpact" format="dateFormat"/> + </dd> + <dt>Locale</dt> + <dd>${locale.displayName}</dd> +</dl> + + +</html> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/94b18f6b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Html5DateFieldDemo.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Html5DateFieldDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Html5DateFieldDemo.java new file mode 100644 index 0000000..2cff7e6 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Html5DateFieldDemo.java @@ -0,0 +1,71 @@ +// Copyright 2007, 2008, 2013, 2014 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.apache.tapestry5.integration.app1.pages; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +import org.apache.tapestry5.annotations.Persist; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.beaneditor.Validate; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.ioc.services.TypeCoercer; +import org.apache.tapestry5.services.PersistentLocale; + +public class Html5DateFieldDemo +{ + @Persist + @Property + private Date birthday; + + @Persist + @Property + @Validate("required") + private Date asteroidImpact; + + @Inject + private PersistentLocale persistentLocale; + + @Inject + private TypeCoercer typeCoercer; + + public DateFormat getDateFormat() + { + return DateFormat.getDateInstance(DateFormat.SHORT, getLocale()); + } + + public Locale getLocale() + { + return persistentLocale.get(); + } + + void onActionFromClear() + { + birthday = null; + asteroidImpact = null; + } + + void onActionFromEnglish() + { + persistentLocale.set(Locale.ENGLISH); + } + + void onActionFromFrench() + { + persistentLocale.set(Locale.FRENCH); + } + +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/94b18f6b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java index 8a238e9..df579be 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java @@ -58,7 +58,9 @@ public class Index private static final List<Item> ITEMS = CollectionFactory .newList( - new Item("PublishEventDemo", "@PublishEvent Demo", "Publishing server-side events to client-side code (JavaScript)"), + new Item("PublishEventDemo", "@PublishEvent Demo", "Publishing server-side events to client-side code (JavaScript)"), + + new Item("Html5DateFieldDemo", "Html5DateField Demo", "Choosing dates using the native HTML5 date picker"), // new Item("ZoneFormDemo", "Zone Form Decoration", "Fields inside an Ajax-updatd Form are still decorated properly."),
