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 > >