Writing custom Submit action for adaptive forms writing-custom-submit-action-for-adaptive-forms

CAUTION
AEM 6.4 has reached the end of extended support and this documentation is no longer updated. For further details, see our technical support periods. Find the supported versions here.

Adaptive forms require Submit actions to process user-specified data. A Submit action determines the task performed on the data that you submit using an adaptive form. Adobe Experience Manager (AEM) includes OOTB Submit actions that demonstrate custom tasks you can perform using the user-submitted data. For example, you can perform tasks, such as sending email or storing the data.

Workflow for a Submit action workflow-for-a-submit-action

The flowchart depicts the workflow for a Submit action that is triggered when you click the Submit button in an adaptive form. The files in the File Attachment component are uploaded to the server, and the form data is updated with the URLs of the uploaded files. Within the client, the data is stored in the JSON format. The client sends an Ajax request to an internal servlet that massages the data you specified and returns it in the XML format. The client collates this data with action fields. It submits the data to the final servlet (Guide Submit servlet) through a Form Submit action. Then, the servlet forwards the control to the Submit action. The Submit action can forward the request to a different sling resource or redirect the browser to another URL.

Flowchart depicting the workflow for Submit action

XML data format xml-data-format

The XML data is sent to the servlet using the jcr:data request parameter. Submit actions can access the parameter to process the data. The following code describes the format of the XML data. The fields that are bound to the Form model appear in the afBoundData section. Unbound fields appear in the afUnoundData section. For more information about the format of the data.xml file, see Introduction to prepopulating adaptive form fields.

<?xml ?>
<afData>
<afUnboundData>
<data>
<field1>value</field2>
<repeatablePanel>
    <field2>value</field2>
</repeatablePanel>
<repeatablePanel>
    <field2>value</field2>
</repeatablePanel>
</data>
</afUnboundData>
<afBoundData>
<!-- xml corresponding to the Form Model /XML Schema -->
</afBoundData>
</afData>

Action fields action-fields

A Submit action can add hidden input fields (using the HTML input tag) to the rendered form HTML. These hidden fields can contain values that it needs while processing form submission. When submitting the form, these field values are posted back as request parameters that the Submit action can use during submission handling. The input fields are called action fields.

For example, a Submit action that also captures the time taken to fill a form can add the hidden input fields startTime and endTime.

A script can supply the values of the startTime and endTime fields when the form renders and before form submission, respectively. The Submit action script post.jsp can then access these fields using request parameters and compute the total time required to fill the form.

File attachments file-attachments

Submit actions can also use the file attachments you upload using the File Attachment component. Submit action scripts can access these files using the sling RequestParameter API. The isFormField method of the API helps identify whether the request parameter is a file or a form field. You can iterate over the Request parameters in a Submit action to identify File Attachment parameters.

The following sample code identifies the file attachments in the request. Next, it reads the data into the file using the Get API. Finally, it creates a Document object using the data and appends it to a list.

RequestParameterMap requestParameterMap = slingRequest.getRequestParameterMap();
for (Map.Entry<String, RequestParameter[]> param : requestParameterMap.entrySet()) {
    RequestParameter rpm = param.getValue()[0];
    if(!rpm.isFormField()) {
        fileAttachments.add(new Document(rpm.get()));
    }
}

Forward path and Redirect URL forward-path-and-redirect-url

After performing the required action, the Submit servlet forwards the request to the forward path. An action uses the setForwardPath API to set the forward path in the Guide Submit servlet.

If the action doesn’t provide a forward path, the Submit servlet redirects the browser using the Redirect URL. The author configures the Redirect URL using the Thank You Page configuration in the Adaptive Form Edit dialog. You can also configure the Redirect URL through the Submit action or the setRedirectUrl API in the Guide Submit servlet. You can also configure the Request parameters sent to the Redirect URL using the setRedirectParameters API in the Guide Submit servlet.

NOTE
An author provides the Redirect URL (using the Thank You Page Configuration). OOTB Submit Actions use the Redirect URL to redirect the browser from the resource that the forward path references.
You can write a custom Submit action that forwards a request to a resource or servlet. Adobe recommends that the script that performs resource handling for the forward path redirect the request to the Redirect URL when the processing completes.

Submit action submit-action

A Submit action is a sling:Folder that includes the following:

  • addfields.jsp: This script provides the action fields that are added to the HTML file during rendition. Use this script to add hidden input parameters required during submission in the post.POST.jsp script.

  • dialog.xml: This script is similar to the CQ Component dialog. It provides configuration information that the author customizes. The fields are displayed in the Submit Actions Tab in the Adaptive Form Edit dialog when you select the Submit action.

  • post.POST.jsp: The Submit servlet calls this script with the data that you submit and the additional data in the previous sections. Any mention of running an action in this page implies running the post.POST.jsp script. To register the Submit action with the adaptive forms to display in the Adaptive Form Edit dialog, add these properties to the sling

    • guideComponentType of type String and value fd/af/components/guidesubmittype
    • guideDataModel of type String that specifies the type of adaptive form for which the Submit action is applicable. xfa is supported for XFA-based adaptive forms while xsd is supported for XSD-based adaptive forms. basic is supported for adaptive forms that do not use XDP or XSD. To display the action on multiple types of adaptive forms, add the corresponding strings. Separate each string by a comma. For example, to make an action visible on XFA- and XSD-based adaptive forms, specify the values xfa and xsd respectively.
    • jcr:description of type String. The value of this property is displayed in the Submit action list in the Submit Actions Tab of the Adaptive Form Edit dialog. The OOTB actions are present in the CRX repository at the location /libs/fd/af/components/guidesubmittype.

Creating a custom Submit action creating-a-custom-submit-action

Perform the following steps to create a custom Submit action that saves the data in the CRX repository and then sends you an email. The adaptive form contains the OOTB Submit action Store Content (deprecated) that saves the data in the CRX repository. In addition, CQ provides a Mail API that can be used to send emails. Before using the Mail API, [configure](https://docs.adobe.com/docs/en/cq/current/administering/notification.html?#Configuring the Mail Service) the Day CQ Mail service through the system console. You can reuse the Store Content (deprecated) action to store the data in the repository. The Store Content (deprecated) action is available at the location /libs/fd/af/components/guidesubmittype/store in the CRX repository.

  1. Log in to CRXDE Lite at the URL https://<server>:<port>/crx/de/index.jsp. Create a node with the property sling:Folder and name store_and_mail in the /apps/custom_submit_action folder. Create the custom_submit_action folder if it doesn’t exist already.

    Screenshot depicting the creation of a node with the property sling:Folder

  2. Provide the mandatory configuration fields.

    Add the configuration the Store action requires. Copy the cq:dialog node of the Store action from /libs/fd/af/components/guidesubmittype/store to the action folder at /apps/custom_submit_action/store_and_email.

    Screenshot showing the copying of the dialog node to the action folder

  3. Provide configuration fields to prompt the author for email configuration.

    The adaptive form also provides an Email action that sends emails to users. Customize this action based on your requirements. Navigate to /libs/fd/af/components/guidesubmittype/email/dialog. Copy the nodes within the cq:dialog node to cq:dialog node of your Submit action (https://experienceleague.adobe.com/apps/custom_submit_action/store_and_email/dialog?lang=en).

    Customizing the email action

  4. Make the action available in the Adaptive Form Edit dialog.

    Add the following properties in the store_and_email node:

    • guideComponentType of type String and value fd/af/components/guidesubmittype
    • guideDataModel of type String and value xfa, xsd, basic
    • jcr:description of type String and value Store and Email Action
  5. Open any adaptive form. Click the Edit button next to Start to open the Edit dialog of the adaptive form container. The new action is displayed in the Submit Actions Tab. Selecting the Store and Email Action displays the configuration added in the dialog node.

    Submit action configuration dialog

  6. Use the action to complete a task.

    Add the post.POST.jsp script to your action. (https://experienceleague.adobe.com/apps/custom_submit_action/store_and_mail/?lang=en).

    Run the OOTB Store action (post.POST.jsp script). Use the FormsHelper.runAction API that CQ provides in your code to run the Store action. Add the following code in your JSP file:

    FormsHelper.runAction("/libs/fd/af/components/guidesubmittype/store", "post", resource, slingRequest, slingResponse);

    To send the email, the code reads the recipient’s email address from the configuration. To fetch the configuration value in the action’s script, read the properties of the current resource using the following code. Similarly you can read the other configuration files.

    ValueMap properties = ResourceUtil.getValueMap(resource);

    String mailTo = properties.get("mailTo");

    Finally, use the CQ Mail API to send the email. Use the SimpleEmail class to create the Email Object as depicted below:

    note note
    NOTE
    Ensure that the JSP file has the name post.POST.jsp.
    code language-java
    <%@include file="/libs/fd/af/components/guidesglobal.jsp" %>
    <%@page import="com.day.cq.wcm.foundation.forms.FormsHelper,
           org.apache.sling.api.resource.ResourceUtil,
           org.apache.sling.api.resource.ValueMap,
                    com.day.cq.mailer.MessageGatewayService,
      com.day.cq.mailer.MessageGateway,
      org.apache.commons.mail.Email,
                    org.apache.commons.mail.SimpleEmail" %>
    <%@taglib prefix="sling"
                    uri="https://sling.apache.org/taglibs/sling/1.0" %>
    <%@taglib prefix="cq"
                    uri="https://www.day.com/taglibs/cq/1.0"
    %>
    <cq:defineObjects/>
    <sling:defineObjects/>
    <%
            String storeContent =
                        "/libs/fd/af/components/guidesubmittype/store";
            FormsHelper.runAction(storeContent, "post", resource,
                                    slingRequest, slingResponse);
     ValueMap props = ResourceUtil.getValueMap(resource);
     Email email = new SimpleEmail();
     String[] mailTo = props.get("mailto", new String[0]);
     email.setFrom((String)props.get("from"));
            for (String toAddr : mailTo) {
                email.addTo(toAddr);
       }
     email.setMsg((String)props.get("template"));
     email.setSubject((String)props.get("subject"));
     MessageGatewayService messageGatewayService =
                        sling.getService(MessageGatewayService.class);
     MessageGateway messageGateway =
                    messageGatewayService.getGateway(SimpleEmail.class);
     messageGateway.send(email);
    %>
    

    Select the action in the adaptive form. The action sends an email and stores the data.

recommendation-more-help
a6ebf046-2b8b-4543-bd46-42a0d77792da