Creating a Custom Option Within the Tools Section in AEM

Mayur Satav
Activate AEM
Published in
6 min readSep 19, 2023

In the world of IT, you never know what types of requirements may arise. To meet the needs of customers, it’s sometimes necessary to go beyond traditional implementations. In this article, we will explore how to create a custom option within the tools section. This custom option will provide an efficient and flexible way to handle various functionalities beyond what is available out of the box.

Let’s break it down step by step.

In this blog article, we will start by overlaying the existing node and then customize it to meet our specific requirements. We’ll also delve into topics like Coral icons, shell pages, and more. Consider this blog as a quick starting point, and you can later build upon it for more advanced customization.

So, let’s embark on our AEM Custom Tools Mission 🚀

Step 1: Create an AEM Tools structure overlay under /apps.

Begin by navigating to the path /libs/cq/core/content/nav/tools, right-click on the tools node, and select the Overlay Node option.

Overlay Node dialog will open. Select the Overlay Location path which is by default it is /apps/ only. Click OK

Then you can see a similar node structure is created under /apps/

Now let’s add our custom option.

Step 2: Create a node of type nt:unstructured under tools.

Then give id as well as jcr:title properties to that node.

Once you are done with Step 2 you can able to see your custom option under the tools.

But right now the option is empty because there is no item created.

Similarly, follow step 2 if you want to create more options under tools.

Create Items

Step 3: To create an item simply create a node of type nt:unstructured under the node you created in Step 2. For me, I created tool1 node under /apps/cq/core/content/nav/tools/mytools node.

Once the node is created, Add id, jcr:title, jcr:description, icon, target and href as per the below screenshot.

  • For more about Adobe coral icons, you can visit Available Icons.
  • A href is a location of the Tool’s landing page that will display the custom tool/dashboard. It can be under /apps/ or /content/.

Once you are done with node creation and properties. Your custom option tool will look like this.

Similarly, follow Step 3 if you want to create more tools under the tab option.

Step 4: Let’s create a separate project folder for our set of tools. Under /apps/ create my-tools node of type nt:folder followed by clientlibs and component nodes of the same type under my-tools.

Under clientlibs create clientlib-base node of type nt:folder and give categories property.

All your custom CSS and JS code will come under this clientlib.

Step 5: To create a basic shell page, simply follow below node hierarchy. Under /apps/my-tools/components create a content node of the type nt:folder. Then again create another node of type cq:page for our page

Once the page is created copy the path of that page and update it for the href property given in Step3 by adding. HTML after the page name.

Once you are done with page creation and href property update, go to the My Tools option and click on Tool1. It will redirect you to our newly created shell page.

http://localhost:4502/apps/my-tools/components/content/tool1.html

Right now it is empty, Next will see how to add a head and title to our shell page.

Step 6: First will create the head for our page.

Under /apps/my-tools/components/content/tool1/jcr:content create the head node of type nt:unstructured.

again under /apps/my-tools/components/content/tool1/jcr:content/head create clientlibs node of type nt:unstructured and give below properties.

Next will add a title for our shell page.

Under /apps/my-tools/components/content/tool1/jcr:content create a title node of type nt:unstructured and add the below properties.

If you refresh the shell page we created, you will see the title added

Now the only missing part is fields, Next will see how to add different granite fields in it.

Step 7: Adding granite fields in the shell page is the same as the creation of a CQ dialog for the components. Follow the below XML for a complete dialog hierarchy.

<?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="cq:Page">
<jcr:content
jcr:primaryType="nt:unstructured"
jcr:title="Tool 1"
sling:resourceType="granite/ui/components/shell/page"
consoleId="tool-one">
<head jcr:primaryType="nt:unstructured">
<clientlibs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs"
categories="[granite.ui.coral.foundation,my-tools.base]"/>
</head>
<title
jcr:primaryType="nt:unstructured"
jcr:title="My Tools - Tool 1"
sling:resourceType="granite/ui/components/shell/title"/>
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<columns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<container
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<well
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/well"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<container
granite:id="fileUploadForm"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form"
enctype="multipart/form-data"
foundationForm="{Boolean}true"
loadingMask="{Boolean}true"
margin="{Boolean}true"
maximized="{Boolean}true"
style="vertical">
<items jcr:primaryType="nt:unstructured">
<pathField
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Enter regex string to get results"
filter="folder"
required="{Boolean}true"
rootPath="/content"/>
<submitButton
granite:id="btnSubmit"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="Submit"
type="submit"/>
</items>
</container>
</items>
</well>
</items>
</container>
</items>
</column>
</items>
</columns>
</items>
</content>
</jcr:content>
</jcr:root>

Once you are done with the creation of dialog. The shell page will look like this.

Now, you can leverage CSS and JavaScript to enhance interactivity and introduce various functionalities.

Congratulations! 🤩 You’re now well-prepared to tackle more advanced customer requirements.

For further details, please refer to the links provided in the references.

References —

--

--