org.wicketstuff.jquery.validation.AjaxFormComponentValidatorBehaviour Maven / Gradle / Ivy
package org.wicketstuff.jquery.validation;
import java.util.List;
import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.Session;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.feedback.ComponentFeedbackMessageFilter;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
/**
 * 
 * Ajax validation behaviour that triggers when the selected event is fired. The default action is
 * to add a css class to the parent element of the component and add any error messages in a span
 * directly after the component. You can change this behaviour by overriding getErrorJavascript().
 * 
 * By default it uses JQuery to do the markup manipulation. You can either skip jquery or load
 * another library by overriding the renderHead method.
 * 
 * This behaviour will also update the model object when the selected client side event fires.
 * 
 * @author Edvin Syse 
 * @created 2008-06-01
 * 
 */
public class AjaxFormComponentValidatorBehaviour extends AjaxFormComponentUpdatingBehavior
{
	private static final long serialVersionUID = 1L;
	public static final String ERROR_COMPONENT_CLASS = "error";
	public static final String ERROR_MESSAGE_CLASS = "error";
	private boolean errorDetected;
	/* Default constructor, attaches to the onblur clientside event */
	public AjaxFormComponentValidatorBehaviour()
	{
		this("onblur");
	}
	public AjaxFormComponentValidatorBehaviour(String event)
	{
		super(event);
		errorDetected = false;
	}
	/**
	 * When the component renders, onUpdate will remove the markup containing any previous
	 * error-message.
	 * 
	 * @param target
	 */
	@Override
	protected void onUpdate(AjaxRequestTarget target)
	{
		if (errorDetected)
		{
			// Remove the error-class on the surrounding element
			target.appendJavaScript("$('#" + getComponent().getMarkupId() + "').removeClass('" +
				ERROR_COMPONENT_CLASS + "');");
			// Remove the previously added error-messages
			target.appendJavaScript(getRemovePreviousErrorsScript());
		}
	}
	/**
	 * Javascript used to remove previously shown error messages.
	 * 
	 * @return
	 */
	protected String getRemovePreviousErrorsScript()
	{
		return "$('#" + getComponent().getMarkupId() + "').next().remove();";
	}
	/**
	 * Adds the error-javascript to the response since the component has errors.
	 * 
	 * @param target
	 *            The AjaxRequestTarget you can add components to
	 * @param e
	 *            The exception if any
	 */
	@Override
	protected void onError(AjaxRequestTarget target, RuntimeException e)
	{
		super.onError(target, e);
		target.appendJavaScript(getErrorJavascript());
		errorDetected = true;
	}
	/**
	 * Returns the javascript that will manipulate the markup to show the error message. Defaults to
	 * adding a CSS-class to the parent element (nice if you add a
	 * 
	 * or 
 around your label/component)
	 * 
	 * @return
	 */
	protected String getErrorJavascript()
	{
		StringBuilder b = new StringBuilder();
		// Remove the previously added error-messages
		if (errorDetected)
			b.append(getRemovePreviousErrorsScript());
		// Add the ERROR class to the sourrounding component
		b.append("$('#" + getComponent().getMarkupId() + "').parent().addClass('" +
			ERROR_COMPONENT_CLASS + "');");
		// Create list of error messages, separated by the chosen separator markup
		List messages = Session.get()
			.getFeedbackMessages()
			.messages(new ComponentFeedbackMessageFilter(getComponent()));
		StringBuilder mb = new StringBuilder("");
		for (int i = 0; i < messages.size(); i++)
		{
			String msg = messages.get(i).getMessage().toString().replace("'", "\\'");
			mb.append(msg);
			if (i + 1 < messages.size())
				mb.append(getErrorSeparator());
		}
		// Add the span with the error messages
		b.append("$('#" + getComponent().getMarkupId() + "').after('" + mb.toString() + "');");
		return b.toString();
	}
	/**
	 * The error separator is used to differentiate each error-message in case a component has more
	 * than one error message
	 * 
	 * Defaults to separating using a 
	 * tag.
	 * 
	 * @return the markup for separating multiple error message
	 */
	protected String getErrorSeparator()
	{
		return "
";
	}
	/**
	 * Add the JQuery library so we can use it in the onError method to manipulate the markup.
	 * 
	 * @param response
	 */
	@Override
	public void renderHead(Component component, IHeaderResponse response)
	{
		super.renderHead(component, response);
		response.render(JavaScriptHeaderItem
			.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference()));
	}
}
    
    
 
    © 2015 - 2025 Weber Informatics LLC | Privacy Policy