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" <mailingl...@nesluop.dk> > To: "Tapestry users" <users@tapestry.apache.org> > Subject: Re: HTML5 Button Component for tapetry 5.4.x > > We usually just style the various Tapestry link components to get buttons > with the desired behavior. > > -- > Chris > > On Wed, Sep 11, 2019 at 1:45 PM Luca Arzeni <l.arz...@iname.com> wrote: > > > Hi there, > > I googled a little around, but I was not able to find a tapestry component > > 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 add 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="submit"> or <input > > type="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="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 can 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 = true; > > > > /** > > * The name of the event that will be triggered if this component > > is the cause of the form submission. The default > > * is {@link EventConstants#SELECTED}. > > */ > > @Parameter(allowNull = false, defaultPrefix = > > BindingConstants.LITERAL) > > private String event = EventConstants.SELECTED; > > > > /** > > * If true, then the field will render out with a disabled > > attribute > > * (to turn off client-side behavior). When the form is submitted, > > the > > * bound value is evaluated again and, if true, the field's value > > is > > * ignored (not even validated) and the component's events are not > > fired. > > */ > > @Parameter("false") > > private boolean disabled; > > > > @Parameter(defaultPrefix = BindingConstants.LITERAL) > > private String type; > > > > /** > > * The list of values that will be made available to event handler > > 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 not > > indicate > > * that the form was cancelled. > > * > > * @see EventConstants#CANCELED > > * @since 5.2.0 > > */ > > @Parameter(allowNull = false, defaultPrefix = > > BindingConstants.LITERAL) > > private SubmitMode mode = SubmitMode.NORMAL; > > > > /** > > * CSS class for the element. > > * > > * @since 5.4 > > */ > > @Parameter(name = "class", defaultPrefix = > > BindingConstants.LITERAL, value = > > "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 = clientId; > > this.elementName = elementName; > > } > > > > public void execute(Html5Button component) > > { > > component.processSubmission(clientId, elementName); > > } > > } > > > > public Html5Button() > > { > > } > > > > Html5Button(Request request) > > { > > this.request = request; > > } > > > > void beginRender(MarkupWriter writer) > > { > > clientId = javascriptSupport.allocateClientId(resources); > > > > String l_name = > > formSupport.allocateControlName(resources.getId()); > > > > // Save the element, to see if an id is later requested. > > > > 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 = > > Holder.create(); > > if (context != null) > > { > > Object[] currentContext = new > > Object[context.length]; > > System.arraycopy(context, 0, currentContext, 0, > > context.length); > > currentContextHolder.put(currentContext); > > } > > > > Runnable sendNotification = new Runnable() > > { > > public void run() > > { > > // TAP5-1024: allow for navigation result > > 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 = > > request.getParameter(Form.SUBMITTING_ELEMENT_ID); > > > > if (InternalUtils.isNonBlank(raw) && > > new > > JSONArray(raw).getString(0).equals(clientId)) > > { > > return true; > > } > > > > String name = elementName; > > > > String value = request.getParameter(name); > > > > return value != null; > > } > > > > /** > > * Returns the component's client id. This must be called after > > the component has rendered. > > * > > * @return client id for the component > > */ > > public String getClientId() > > { > > return clientId; > > } > > } > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > > For additional commands, e-mail: users-h...@tapestry.apache.org > > > > >
--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org