ADOBE EXPERIENCE MANAGER (AEM) COMPONENTS
Concept Code Component
An Adobe Experience Manager (AEM) example to demonstrate development of a component for adding concept code to a page using a textarea field. Can be used for testing, prototyping and troubleshooting.
Getting Started
We’re using a AEM Project Archetype Maven template to create the project.
For example,
cd src
mvn -B org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=43 \
-D aemVersion=6.5.0 \
-D appTitle="My Project" \
-D appId="myproject" \
-D groupId="com.myproject" \
-D language=en \
-D country=us \
-D singleCountry=n \
-D frontendModule=general
Component Folder
Copy the existing helloworld
component included with the project to jump start development. For example,
cd src/myproject/ui.apps/src/main/content/jcr_root/apps/myproject/components
cp -a helloworld/. conceptcode/
Update the jcr:root
properties for the conceptcode
component in the conceptcode/.content.xml
as follows.
.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="Concept Code"
componentGroup="My Project - Content"/>
Component Dialog
If you copied the helloworld
component, you should already have a dialog to start with. Otherwise, create a folder named _cq_dialog
in the conceptcode
folder.
The dialog will contain a single textarea for the concept code.
Here is the new XML to use for the apps/myproject/components/conceptcode/_cq_dialog/.content.xml
_cq_dialog/.content.xml
<?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"
xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Properties"
sling:resourceType="cq/gui/components/authoring/dialog"
extraClientlibs="[myproject.cmpconfig.dialog]">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
granite:class="concept-code">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<code
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Code"
name="./code"/>
</items>
</column>
</items>
</content>
</jcr:root>
Let’s go over the changes to the dialog XML above.
-
The obvious change mentioned above was to use a
textarea
field for the code. This is apparent in thecode
element where thesling:resourceType
attribute is set to granite/ui/components/coral/foundation/form/textarea. -
In the
jcr:root
element, we’re adding a namespace attribute for the granite document,xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
. This is for thegranite:class
attribute in change number 4 below. -
Also in the
jcr:root
element, we’re adding anextraClientlibs
attribute with themyproject.cmpconfig.dialog
category specified. This attribute value contains an array for all of the extra client-libs the dialog depends on. The client-lib and its category will be created further down in this tutorial. -
In the
content
element, we’re adding an attribute to apply a CSS class to the markup that is output for the.coral-FixedColumn
container. By doing this we can apply our dialog CSS just for the elements within the container. Steps on where to add the respective CSS further down.
Component Template
Here is the new HTL (Sightly) to use for the apps/myproject/components/conceptcode/conceptcode.html
. If you copied the helloworld
component, the following replaces all of the pre-existing HTL.
conceptcode.html
<sly data-sly-set.emptyText="${properties.code ? 'Configured' : ''}"/>
${properties.code @ context = 'unsafe'}
<sly data-sly-use.templates="/apps/core/wcm/components/commons/v1/templates.html"
data-sly-call="${templates.placeholder @ isEmpty = true, emptyTextAppend = emptyText}" />
The emptyText
variable is used to provide a placeholder label for the container in editmode
so it isn’t collapsed or hidden.
If the properties.code
textarea field is not empty, the label will show “Configured”.
Dialog CSS
This is how the dialog and code entry textarea looks prior to our extraClientLibs
CSS.
Create a new clientlib-dialog
folder that contains a css
folder in the project’s clientlibs
. For example,
cd src/myproject/ui.apps/src/main/content/jcr_root/apps/myproject/clientlibs
mkdir -p clientlib-dialog/css
Create this dialog.less
(Leaner Style Sheets) file in the css folder.
css/dialog.less
.concept-code {
.coral-Form-fieldwrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.coral-FixedColumn-column {
width: 100%;
height: 100%;
}
.coral-Form-field.coral3-Textfield {
height: 100%;
}
}
Create this css.txt
file in the clientlib-dialog
folder.
css.txt
#base=css
dialog.less
#base=css
sets the root as the folder namedcss
below thecq:ClientLibraryFolder
.dialog.less
sets the path of the source files relative to the root folder.
In the clientlib-dialog
folder, create a .content.xml
to define the client library properties. Note that the jcr:root
element contains the categories
attribute [myproject.cmpconfig.dialog]
for the dialog’s extraClientLibs
mapping.
.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
allowProxy="{Boolean}true"
cssProcessor="[default:none,min:none]"
categories="[myproject.cmpconfig.dialog]"
dependencies="[granite.utils]"/>
Adobe Experience League Documentation: Using Client-Side Libraries
With the CSS being applied from the myproject.cmpconfig.dialog
category, the textarea fills the width and remaining height of the column container.
Example dialog with inline script entered into the code textarea.
After saving the dialog, the page renders with the updated code.
Install
You can use mvn clean install to build and deploy it. e.g.,
mvn -PautoInstallPackage clean install
Source Code
Part 6 of 6 in the AEM Component Dev series.