January 2, 2021
Estimated Post Reading Time ~

Component Unique ID

Often times, you need a unique ID for the AEM component. You either need to trigger custom action with JS or make a backend server-side call. A hard-coded field ID is not unique if the component is dragged and dropped multiple times on the page. This post will give you a quick tip to create a unique component ID in AEM, the Adobe way.

When you are thinking about ID, you may think of using the global HTL objects and getters directly, for example: ${currentNode.name}. However, this will not solve the problem if the component is used in different containers on the same page. How about ${currentNode.identifier}? While this JCR node level API returns a unique id for the current node, it contains the node path and forward slashes in the id, which exposes internal content structure and makes it difficult to use in CSS and JS without escaping.

The way Adobe implements it is to generate from resource path, with an ID prefix variable. The core of this solution is that ID can be injected from JCR content directly, or generated from the resource path. For example, if you have an OSGI service or dialog that saves the component ID attribute in JCR, it will honor and use that, instead of generating a new one. If the component doesn’t have an ID attribute, the solution will form the ID by cascading an ID prefix, hyphen, and hash code of the component’s resource path. 

We know that the resource path will always be unique even the component is used multiple times and in a different level of containers. The hash code encapsulates and hides internal path information to the end-user, and makes the id attribute easily used by CSS and JS. To make the ID attribute more human-readable, the developer passes in the ID prefix. Below is a snippet of AbstractComponentModel.java. The component sling model should extend this class and override the getIDPrefix().

public abstract class AbstractComponentModel {
    @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)
    protected String id;
    protected abstract String getIDPrefix();
    @SlingObject
    private Resource resource;
    public String getId() {
    if (id == null) {
        id = getIDPrefix() + "-" +    
        String.valueOf(Math.abs(resource.getPath().hashCode() - 1));
    }
        return id;
    }
}


I have implemented this solution for the title component in my blog demo project. I updated the POM files and tested the code in AEM 6.4. The latest code is in the master branch, where it’s runnable in AEM 6.4. I also created a “release/aem-6.3” branch for my previous code that’s deployable in AEM 6.3. Below is a screenshot of what the title component ID looks like.

We’d love to hear from you! Leave a comment and share any additional thoughts or insights you have.


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.