Re: HTML5 Button Component for tapetry 5.4.x

"Luca Arzeni" <[email protected]> Fri, 13 Sep 2019 18:42:53 +0200
Newsgroups gmane.comp.java.tapestry.user
Message-ID <trinity-7d6619ac-fb41-4d41-addb-61fbb51309e5-1568392973422@3c-app-mailcom-lxa07>
Hi Chris,
see the reply to Thiago for my use case.
Thanks,
Luca

> Sent: Wednesday, September 11, 2019 at 2:58 PM
> From: "Chris Poulsen" <[email protected]>
> To: "Tapestry users" <[email protected]>
> Subject: Re: HTML5 Button Component for tapetry 5.4.x
>
> We usually just style the various Tapestry link components to get button=
s
> with the desired behavior.
>
> --
> Chris
>
> On Wed, Sep 11, 2019 at 1:45 PM Luca Arzeni <[email protected]> wrote:
>
> > Hi there,
> > I googled a little around, but I was not able to find a tapestry compo=
nent
> > that generates a button.
> >
> > Here you can find a first attempt to create such component.
> > It was shameless copied from the Submit component already present in
> > tapestry.
> >
> > I would be happy if someone more expert than me could revise it and ad=
d to
> > the core components.
> >
> > Regards,
> > larzeni
> >
> > package org.apache.tapestry5.corelib.components;
> >
> > import org.apache.tapestry5.BindingConstants;
> > import org.apache.tapestry5.ClientElement;
> > import org.apache.tapestry5.ComponentAction;
> > import org.apache.tapestry5.ComponentResources;
> > import org.apache.tapestry5.EventConstants;
> > import org.apache.tapestry5.MarkupWriter;
> > import org.apache.tapestry5.TrackableComponentEventCallback;
> > import org.apache.tapestry5.annotations.Environmental;
> > import org.apache.tapestry5.annotations.Events;
> > import org.apache.tapestry5.annotations.Import;
> > import org.apache.tapestry5.annotations.Parameter;
> > import org.apache.tapestry5.annotations.SupportsInformalParameters;
> > import org.apache.tapestry5.corelib.SubmitMode;
> > import org.apache.tapestry5.corelib.components.Form;
> > import org.apache.tapestry5.corelib.components.Loop;
> > import org.apache.tapestry5.internal.util.Holder;
> > import org.apache.tapestry5.ioc.annotations.Inject;
> > import org.apache.tapestry5.ioc.internal.util.InternalUtils;
> > import org.apache.tapestry5.json.JSONArray;
> > import org.apache.tapestry5.services.FormSupport;
> > import org.apache.tapestry5.services.Heartbeat;
> > import org.apache.tapestry5.services.Request;
> > import org.apache.tapestry5.services.javascript.JavaScriptSupport;
> >
> > /**
> >  * Corresponds to <input type=3D"submit"> or <input
> > type=3D"image">, a client-side element that can force the
> >  * enclosing form to submit. The submit responsible for the form
> > submission will post a notification that allows the
> >  * application to know that it was the responsible entity. The
> > notification is named
> >  * {@linkplain EventConstants#SELECTED selected}, by default, and has =
no
> > context.
> >  *
> >  * @tapestrydoc
> >  */
> > @SupportsInformalParameters
> > @Events(EventConstants.SELECTED + " by default, may be overridden")
> > @Import(module=3D"t5/core/forms")
> > public class Html5Button implements ClientElement {
> >
> >         /**
> >          * If true (the default), then any notification sent by the
> > component will be deferred until the end of the form
> >          * submission (this is usually desirable). In general, this ca=
n be
> > left as the default except when the Submit
> >          * component is rendering inside a {@link Loop}, in which case
> > defer should be bound to false (otherwise, the
> >          * event context will always be the final value of the Loop).
> >          */
> >         @Parameter
> >         private boolean defer =3D true;
> >
> >         /**
> >          * The name of the event that will be triggered if this compon=
ent
> > is the cause of the form submission. The default
> >          * is {@link EventConstants#SELECTED}.
> >          */
> >         @Parameter(allowNull =3D false, defaultPrefix =3D
> > BindingConstants.LITERAL)
> >         private String event =3D EventConstants.SELECTED;
> >
> >         /**
> >          * If true, then the field will render out with a disabled
> > attribute
> >          * (to turn off client-side behavior). When the form is submit=
ted,
> > the
> >          * bound value is evaluated again and, if true, the field's va=
lue
> > is
> >          * ignored (not even validated) and the component's events are=
 not
> > fired.
> >          */
> >         @Parameter("false")
> >         private boolean disabled;
> >
> >         @Parameter(defaultPrefix =3D BindingConstants.LITERAL)
> >         private String type;
> >
> >         /**
> >          * The list of values that will be made available to event han=
dler
> > method of this component when the form is
> >          * submitted.
> >          *
> >          * @since 5.1.0.0
> >          */
> >         @Parameter
> >         private Object[] context;
> >
> >         /**
> >          * Defines the mode, or client-side behavior, for the submit. =
The
> > default is {@link SubmitMode#NORMAL}; clicking the
> >          * button submits the form with validation. {@link
> > SubmitMode#CANCEL} indicates the form should be submitted as a cancel,
> >          * with no client-side validation. {@link
> > SubmitMode#UNCONDITIONAL} bypasses client-side validation, but does no=
t
> > indicate
> >          * that the form was cancelled.
> >          *
> >          * @see EventConstants#CANCELED
> >          * @since 5.2.0
> >          */
> >         @Parameter(allowNull =3D false, defaultPrefix =3D
> > BindingConstants.LITERAL)
> >         private SubmitMode mode =3D SubmitMode.NORMAL;
> >
> >         /**
> >          * CSS class for the element.
> >          *
> >          * @since 5.4
> >          */
> >         @Parameter(name =3D "class", defaultPrefix =3D
> > BindingConstants.LITERAL, value =3D
> > "message:private-core-components.submit.class")
> >         private String cssClass;
> >
> >         @Environmental
> >         private FormSupport formSupport;
> >
> >         @Environmental
> >         private Heartbeat heartbeat;
> >
> >         @Inject
> >         private ComponentResources resources;
> >
> >         @Inject
> >         private Request request;
> >
> >         @Inject
> >         private JavaScriptSupport javascriptSupport;
> >
> >         @SuppressWarnings("rawtypes")
> >         @Environmental
> >         private TrackableComponentEventCallback eventCallback;
> >
> >         private String clientId;
> >
> >         @SuppressWarnings("serial")
> >         private static class ProcessSubmission implements
> > ComponentAction<Html5Button>
> >         {
> >                 private final String clientId, elementName;
> >
> >                 public ProcessSubmission(String clientId, String
> > elementName)
> >                 {
> >                         this.clientId =3D clientId;
> >                         this.elementName =3D elementName;
> >                 }
> >
> >                 public void execute(Html5Button component)
> >                 {
> >                         component.processSubmission(clientId, elementN=
ame);
> >                 }
> >         }
> >
> >         public Html5Button()
> >         {
> >         }
> >
> >         Html5Button(Request request)
> >         {
> >                 this.request =3D request;
> >         }
> >
> >         void beginRender(MarkupWriter writer)
> >         {
> >                 clientId =3D javascriptSupport.allocateClientId(resour=
ces);
> >
> >                 String l_name =3D
> > formSupport.allocateControlName(resources.getId());
> >
> >                 // Save the element, to see if an id is later requeste=
d.
> >
> >                 writer.element("button",
> >
> >                                                 "type", type,
> >
> >                                                 "name", l_name,
> >
> >                                                 "data-submit-mode",
> > mode.name().toLowerCase(),
> >
> >                                                 "class", cssClass,
> >
> >                                                 "id", clientId);
> >
> >                 if (disabled)
> >                 {
> >                         writer.attributes("disabled", "disabled");
> >                 }
> >
> >                 formSupport.store(this, new ProcessSubmission(clientId=
,
> > l_name));
> >
> >                 resources.renderInformalParameters(writer);
> >         }
> >
> >         void afterRender(MarkupWriter writer)
> >         {
> >                 writer.end();
> >         }
> >
> >         void processSubmission(String clientId, String elementName)
> >         {
> >                 if (disabled || !selected(clientId, elementName))
> >                         return;
> >
> >                 // TAP5-1658: copy the context of the current Submit
> > instance so we trigger the event with
> >                 // the correct context later
> >                 final Holder<Object[]> currentContextHolder =3D
> > Holder.create();
> >                 if (context !=3D null)
> >                 {
> >                         Object[] currentContext =3D new
> > Object[context.length];
> >                         System.arraycopy(context, 0, currentContext, 0=
,
> > context.length);
> >                         currentContextHolder.put(currentContext);
> >                 }
> >
> >                 Runnable sendNotification =3D new Runnable()
> >                 {
> >                         public void run()
> >                         {
> >                                 // TAP5-1024: allow for navigation res=
ult
> > from the event callback
> >                                 resources.triggerEvent(event,
> > currentContextHolder.get(), eventCallback);
> >                         }
> >                 };
> >
> >                 // When not deferred, don't wait, fire the event now
> > (actually, at the end of the current
> >                 // heartbeat). This is most likely because the Submit =
is
> > inside a Loop and some contextual
> >                 // information will change if we defer.
> >
> >                 if (defer)
> >                         formSupport.defer(sendNotification);
> >                 else
> >                         heartbeat.defer(sendNotification);
> >         }
> >
> >         private boolean selected(String clientId, String elementName)
> >         {
> >                 // Case #1: via JavaScript, the client id is passed up=
.
> >
> >                 String raw =3D
> > request.getParameter(Form.SUBMITTING_ELEMENT_ID);
> >
> >                 if (InternalUtils.isNonBlank(raw) &&
> >                                                 new
> > JSONArray(raw).getString(0).equals(clientId))
> >                 {
> >                         return true;
> >                 }
> >
> >                 String name =3D elementName;
> >
> >                 String value =3D request.getParameter(name);
> >
> >                 return value !=3D null;
> >         }
> >
> >         /**
> >          * Returns the component's client id. This must be called afte=
r
> > the component has rendered.
> >          *
> >          * @return client id for the component
> >          */
> >         public String getClientId()
> >         {
> >                 return clientId;
> >         }
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]