Loading Now

AEM: Sightly Dialog Validation

sightly-dialog-validation

AEM: Sightly Dialog Validation

In Adobe Experience Manager (AEM), a Sightly dialog (based on the cq:dialog node) can include various structural nodes such as panels and tabs. Within these structures, you can add input components like text fields, dropdowns, and radio buttons.
This guide explains how to implement basic custom validation for these dialog fields.

Step 1: Create a Client Library

Create a client library under your component’s main folder with the following properties:

jcr:primaryType="cq:ClientLibraryFolder"
allowProxy="{Boolean}true"
categories="[com.myApp.bannerTeaser.validation]" (use a unique category name)
dependencies="[granite.jquery, granite.utils]"

Step 2: Add JavaScript for Validation

Create a JavaScript file in the clientlib folder and implement your validation logic. There are multiple approaches:

<label
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/foundation/form/textfield"
    fieldLabel="Label"
    validation="my-component-validation"
    name="./label"/>

Option 1: Validation Attribute

  • Register a custom validator and add your logic.
  • Ideal for common validations across multiple dialogs (e.g., ensuring only two tags are selected).
registry.register("foundation.validation.validator", {
    selector: "[data-validation=my-component-validation]",
    validate: function (element) {
        var field, value;
        field = $(element);
        value = $(field).val();
        if (value == undefined || value == "") {
            return "Please add correct value";
        } else {
            return;
        }
    },
    show: function (element, message, ctx) {
        $(element).closest(".my-component-wrapper").adaptTo("foundation-field").setInvalid(true);
        ctx.next();
    },
    clear: function (element, ctx) {
        $(element).closest(".my-component-wrapper").adaptTo("foundation-field").setInvalid(false);
        ctx.next();
    }
});

Option 2: Foundation Validation API

Use AEM’s Foundation Validation API to validate input and update the UI dynamically.

var validateHandler = function (e) {
        var myComponent = $(document).find("[data-validation=my-component-validation]");
        var validator = $(myComponent).adaptTo("foundation-validation");
        if (validator) {
                validator.checkValidity();
                validator.updateUI();
        }
};
$(document).on("dialog-ready", function () {
        var container = $(this).find(".my-component-wrapper");
        if (container.length > 0) {
                $('.my-component-wrapper').on('focusout', function (e) {
                        (validateHandler(e);
                });
        }
});

Option 3: Custom JavaScript/jQuery

  • Directly read input values using JavaScript/jQuery.
  • Display error messages using custom CSS for a tailored UI experience.

Step 3: Backend Validation (Optional)

  • For validations requiring backend checks (e.g., verifying if a node exists or checking OSGi configuration values):
  • Implement logic in a Servlet.
  • Call the servlet from the frontend using Fetch API.
  • Process the response and update the UI accordingly.
@Component(service = Servlet.class, property = {
        ServletResolverConstants.SLING_SERVLET_METHODS + "=" + HttpConstants.METHOD_GET,
        ServletResolverConstants.SLING_SERVLET_PATHS + "=/bin/mycomponent/validation"
}, immediate = true)
public class MyComponentValidationServlet extends SlingSafeMethodsServlet {
    @Override
    protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response)
            throws ServletException, IOException {
        try {
            // Perform your validation logic here
            writeResponse(response, isValid);
        } catch (IOException e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private void writeResponse(SlingHttpServletResponse response, boolean isValid) throws IOException {
        JsonObject statusJson = new JsonObject();
        statusJson.addProperty("isValid", isValid);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setContentType("application/json");
        response.getWriter().write(statusJson.toString());
        response.setStatus(HttpServletResponse.SC_OK);
    }
}

Step 4: Include JS and CSS

Create a js.txt file inside the clientlib folder and list your JS files (one per line). Optionally, create a css.txt file to include custom CSS files.

Step 5: Include Clientlib in Dialog

To activate the validation logic, include the clientlib in your component dialog using the

extraClientlibs property and specify the category name you defined in Step 1

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured"
    jcr:title="My Component"
    extraClientlibs="[com.myApp.bannerTeaser.validation]"
    sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            ...
        </items>
    </content>
</jcr:root>

Or use resource “granite/ui/components/coral/foundation/includeclientlibs”

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured"
    jcr:title="My Component"
    sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <includeClientlibs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs"
                categories="[com.myApp.bannerTeaser.validation]"/>
            <tabs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs">
                ...
            </tabs>
        </items>
    </content>
</jcr:root>

Key Benefits

  • Ensures data integrity and better user experience.
  • Prevents invalid configurations from being saved.
  • Provides flexibility for both frontend and backend validations.

Post Comment