org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.wicket.ajax.form;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IFormSubmitter;
import org.apache.wicket.markup.html.form.IFormSubmittingComponent;
import org.apache.wicket.util.lang.Args;
import org.danekja.java.util.function.serializable.SerializableConsumer;

/**
 * Ajax event behavior that submits a form via ajax when the event it is attached to, is invoked.
 * <p>
 * The form must have an id attribute in the markup or have MarkupIdSetter added.
 * 
 * @see AjaxEventBehavior
 * 
 * @since 1.2
 * 
 * @author Igor Vaynberg (ivaynberg)
 * @see #onSubmit(org.apache.wicket.ajax.AjaxRequestTarget)
 * @see #onAfterSubmit(org.apache.wicket.ajax.AjaxRequestTarget)
 * @see #onError(org.apache.wicket.ajax.AjaxRequestTarget)
 */
public abstract class AjaxFormSubmitBehavior extends AjaxEventBehavior {
    private static final long serialVersionUID = 1L;

    /**
     * should never be accessed directly (thus the __ cause its overkill to create a super class),
     * instead always use #getForm()
     */
    private Form<?> __form;

    private boolean defaultProcessing = true;

    /**
     * Constructor. This constructor can only be used when the component this behavior is attached
     * to is inside a form.
     * 
     * @param event
     *            javascript event this behavior is attached to, like onclick
     */
    public AjaxFormSubmitBehavior(String event) {
        this(null, event);
    }

    /**
     * Construct.
     * 
     * @param form
     *            form that will be submitted
     * @param event
     *            javascript event this behavior is attached to, like onclick
     */
    public AjaxFormSubmitBehavior(Form<?> form, String event) {
        super(event);
        __form = form;

        if (form != null) {
            form.setOutputMarkupId(true);
        }
    }

    /**
     * @return Form that will be submitted by this behavior
     */
    public final Form<?> getForm() {
        if (__form == null) {
            __form = findForm();

            if (__form == null) {
                throw new IllegalStateException("form was not specified in the constructor and cannot "
                        + "be found in the hierarchy of the component this behavior " + "is attached to: Component="
                        + getComponent().toString(false));
            }
        }
        return __form;
    }

    /**
     * @return the bound component if it implements {@link org.apache.wicket.markup.html.form.IFormSubmittingComponent},
     * otherwise - {@code null}
     */
    private IFormSubmittingComponent getFormSubmittingComponent() {
        IFormSubmittingComponent submittingComponent = null;
        Component component = getComponent();
        if (component instanceof IFormSubmittingComponent) {
            submittingComponent = ((IFormSubmittingComponent) component);
        }
        return submittingComponent;
    }

    /**
     * Finds form that will be submitted
     * 
     * @return form to submit or {@code null} if none found
     */
    protected Form<?> findForm() {
        // try to find form in the hierarchy of owning component
        Component component = getComponent();
        if (component instanceof Form<?>) {
            return (Form<?>) component;
        } else {
            return component.findParent(Form.class);
        }
    }

    @Override
    protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
        super.updateAjaxAttributes(attributes);

        Form<?> form = getForm();
        attributes.setFormId(form.getMarkupId());

        String formMethod = form.getMarkupAttributes().getString("method");
        if (formMethod == null || "POST".equalsIgnoreCase(formMethod)) {
            attributes.setMethod(Method.POST);
        }

        if (form.getRootForm().isMultiPart()) {
            attributes.setMultipart(true);
            attributes.setMethod(Method.POST);
        }

        IFormSubmittingComponent submittingComponent = getFormSubmittingComponent();
        if (submittingComponent != null) {
            String submittingComponentName = submittingComponent.getInputName();
            attributes.setSubmittingComponentName(submittingComponentName);
        }
    }

    @Override
    protected void onEvent(final AjaxRequestTarget target) {
        AjaxFormSubmitBehavior.AjaxFormSubmitter submitter = new AjaxFormSubmitBehavior.AjaxFormSubmitter(this,
                target);
        Form<?> form = getForm();

        form.getRootForm().onFormSubmitted(submitter);
    }

    /**
     * A publicly reachable class that allows to introspect the submitter, e.g. to
     * check what is the input name of the submitting component if there is such.
     */
    public static class AjaxFormSubmitter implements IFormSubmitter {
        private final AjaxFormSubmitBehavior submitBehavior;
        private final AjaxRequestTarget target;

        private AjaxFormSubmitter(AjaxFormSubmitBehavior submitBehavior, AjaxRequestTarget target) {
            this.submitBehavior = submitBehavior;
            this.target = target;
        }

        @Override
        public Form<?> getForm() {
            return submitBehavior.getForm();
        }

        /**
         * @return the {@link IFormSubmittingComponent} 
         */
        public IFormSubmittingComponent getFormSubmittingComponent() {
            return submitBehavior.getFormSubmittingComponent();
        }

        @Override
        public boolean getDefaultFormProcessing() {
            return submitBehavior.getDefaultProcessing();
        }

        @Override
        public void onError() {
            submitBehavior.onError(target);
        }

        @Override
        public void onSubmit() {
            submitBehavior.onSubmit(target);
        }

        @Override
        public void onAfterSubmit() {
            submitBehavior.onAfterSubmit(target);
        }
    }

    /**
     * Override this method to provide special submit handling in a multi-button form. This method
     * will be called <em>after</em> the form's onSubmit method.
     * @param target the {@link AjaxRequestTarget}
     */
    protected void onAfterSubmit(AjaxRequestTarget target) {
    }

    /**
     * Override this method to provide special submit handling in a multi-button form. This method
     * will be called <em>before</em> the form's onSubmit method.
     * @param target the {@link AjaxRequestTarget}
     */
    protected void onSubmit(AjaxRequestTarget target) {
    }

    /**
     * Listener method invoked when the form has been processed and errors occurred
     * 
     * @param target
     */
    protected void onError(AjaxRequestTarget target) {
    }

    /**
     * @see Button#getDefaultFormProcessing()
     * 
     * @return {@code true} for default processing
     */
    public boolean getDefaultProcessing() {
        return defaultProcessing;
    }

    /**
     * @see Button#setDefaultFormProcessing(boolean)
     * @param defaultProcessing
     */
    public void setDefaultProcessing(boolean defaultProcessing) {
        this.defaultProcessing = defaultProcessing;
    }

    /**
     * Creates an {@link AjaxFormSubmitBehavior} based on lambda expressions
     * 
     * @param eventName
     *            the event name
     * @param onSubmit
     *            the {@code SerializableConsumer} which accepts the {@link AjaxRequestTarget}
     * @return the {@link AjaxFormSubmitBehavior}
     */
    public static AjaxFormSubmitBehavior onSubmit(String eventName,
            SerializableConsumer<AjaxRequestTarget> onSubmit) {
        Args.notNull(onSubmit, "onSubmit");

        return new AjaxFormSubmitBehavior(eventName) {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target) {
                onSubmit.accept(target);
            }
        };
    }
}