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