We all know that when we add an AEM component to a page, it creates the DOM structure on the pages based upon our HTL file.
Sometimes we require id attribute to be set in our div for n number of reasons. If we put id attribute in the HTL file itself then it will become static and if in include that component multiple times on the page, the same id will be repeated for all instance; which is not a neat solution.
Wouldn't it be nice if we have a mechanism to generate an id randomly and uniquely for each instance of the component on the page? In this post, we are going to do just that.
Hence, without further ado, let's get started -
Here, we are calling a SlingModel called IdGeneratorModel which returns the unique id which we are setting as an id attribute.
The above code is nothing but a sling model that takes the prefix field from the HTL code and prepend it to the generated random id. We are then setting that value in the JCR so that the component dialog can read it from there.
Sometimes we require id attribute to be set in our div for n number of reasons. If we put id attribute in the HTL file itself then it will become static and if in include that component multiple times on the page, the same id will be repeated for all instance; which is not a neat solution.
Wouldn't it be nice if we have a mechanism to generate an id randomly and uniquely for each instance of the component on the page? In this post, we are going to do just that.
Hence, without further ado, let's get started -
Step #1
Create a component that will have the field for unique id. We are making this id editable as well to give more flexibility to the content authors. Below is the cq:dialog.xml file -
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/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="ID Demo" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/tabs" type="nav"/> <items jcr:primaryType="nt:unstructured"> <tab jcr:primaryType="nt:unstructured" jcr:title="Properties" sling:resourceType="granite/ui/components/foundation/container"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/> <items jcr:primaryType="nt:unstructured"> <columns jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <uniqueId jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" class="field-whitespace" fieldDescription="Enter the unique id" fieldLabel="ID*" name="./uniqueId" required="{Boolean}true"/> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" class="field-whitespace" fieldDescription="Enter the title" fieldLabel="Title" name="./title"/> <description jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textarea" class="field-whitespace" fieldDescription="Enter the description" fieldLabel="Description" name="./description"/> </items> </columns> </items> </tab> </items> </content> </jcr:root>
Step #2
Create the HTL file with the following code -
<sly data-sly-use.id="${'org.redquark.demo.core.models.IdGeneratorModel' @ prefix='idDemo_'}" /> <div id="${properties.uniqueId}"> ID Demo - #${properties.uniqueId} <div> <h3>Title: ${text.title}</h1> <p>Description: ${text.description}</p> </div> </div>
Step #3
We are now going to create the java code that will create a random id of 8 characters and then return it to the HTL file -
package org.redquark.demo.core.models; import java.nio.charset.Charset; import java.util.Random; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class generates a random id for the main div tag of any component * * @author Anirudh Sharma */ @Model(adaptables = { Resource.class, SlingHttpServletRequest.class }) public class IdGeneratorModel { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Inject private String prefix; @SlingObject private SlingHttpServletRequest request; @PostConstruct protected void init() { // Getting the reference of the current node Node currentNode = request.getResource().adaptTo(Node.class); // Stored id, if any String storedId = null; try { // Getting the stored id from the node storedId = currentNode.getProperty("uniqueId").getString(); } catch (RepositoryException e) { log.error(e.getMessage(), e); } try { if (storedId == null || storedId.isEmpty()) { currentNode.setProperty("uniqueId", prefix + "_" + generateId(8)); request.getResourceResolver().adaptTo(Session.class).save(); } } catch (RepositoryException e) { log.error(e.getMessage(), e); } } /** * This method generates the random id * * @return {@link String} */ private String generateId(int n) { // Length is bounded by 256 Character byte[] array = new byte[256]; new Random().nextBytes(array); String randomString = new String(array, Charset.forName("UTF-8")); // Create a StringBuffer to store the result StringBuffer r = new StringBuffer(); // Append first 20 alphanumeric characters // from the generated random String into the result for (int k = 0; k < randomString.length(); k++) { char ch = randomString.charAt(k); if (((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) && (n > 0)) { r.append(ch); n--; } } // return the resultant string return r.toString(); } }
Step #4
Add the component on the page and inspect it using the browser's dev tools. The id will be set as follows -
Conclusion
So in this post, we saw how we can generate a random and unique id for a component when it is added to any page. You can find the code to this in my GitHub repository.
Comments
Post a Comment