How to Generate Unique AEM Component ID with Confidence

You frequently require a special ID for the AEM component. Either a backend server-side call or a custom JS action trigger are required. If the component is dragged and placed on the page more than once, the hard-coded field ID is not guaranteed to be unique.

When considering ID, you might consider directly using the global HTL objects and getters, such as ${currentNode.name}. If the component is used in other containers on the same page, this will not, however, fix the issue. Despite the fact that the JCR node level API produces a distinct id for the current node, the id also includes the node path and forward slashes, exposing the internal content structure and making it challenging to utilize in CSS and JS without escaping.

The id element is made simple to use by CSS and JS by the hash code, which also encapsulates and hides internal path information from the end-user. The developer passes in the ID prefix to make the ID property easier for humans to read. Example code of a Java Sling Model class is provided below.


Sightly

1
2
3
4
5
6
<sly data-sly-use.componentId="com.sourcedcode.core.models.utils.ComponentId"></sly>
<div id="${componentId.id}" class="cmp-header">
</div>

// this produces
<div id="cmpheader3901793341" class="cmp-header"></div>

Java Sling Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.sourcedcode.core.models.utils;

import com.day.cq.wcm.api.components.Component;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;

@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ComponentId {
 
  @ScriptVariable
  private Component component;
 
  @SlingObject
  private Resource resource;
 
  public String getId() {
    return component.getName() + "-" + String.valueOf(Math.abs(resource.getPath().hashCode() - 1));
  }
}

Last Thoughts

You can improve this setup by adding an “advanced” tab in the component’s Touch UI dialog to have authors insert their own custom component ID. If the author’s configuration is empty, this mechanism will be kicked in to use the ComponentId Sling Model to generate the Ids.

1
2
3
4
5
6
<sly data-sly-use.componentId="com.sourcedcode.core.models.utils.ComponentId"></sly>
<div id="${properties.customComponentId || componentId.id}" class="cmp-header">
</div>

// this produces
<div id="cmpheader3901793341" class="cmp-header"></div>

Was this post helpful?

Hello, I am an active Adobe Community Advisor & a certified Lead AEM Developer who is currently working as a Senior AEM Full Stack Developer. I have over a decade of overall web engineering experience and many years (more than 6) of AEM experience in practice. I hope to give back to the AEM Full Stack Development community by sharing my knowledge with the world.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top