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

Reply via email to