In this chapter, let’s explore the underlying technology of an Adobe Experience Manager (AEM) Sites Component through a simple HelloWorld
example. Small modifications are made to an existing component, covering topics of authoring, HTL, Sling Models, Client-side libraries.
Review the required tooling and instructions for setting up a local development environment.
The IDE used in the videos is Visual Studio Code and the VSCode AEM Sync plugin.
In this chapter, you perform several modifications to a simple HelloWorld
component. While making updates to the HelloWorld
component, you learn about the key areas of AEM component development.
This chapter builds upon a generic project generated by the AEM Project Archetype. Watch the below video and review the prerequisites to get started!
If you successfully completed the previous chapter, you can reuse the project and skip the steps for checking out the starter project.
Open a new command-line terminal and perform the following actions.
In an empty directory, clone the aem-guides-wknd repository:
$ git clone git@github.com:adobe/aem-guides-wknd.git --branch tutorial/component-basics-start --single-branch
Optionally, you can continue using the project generated in the previous chapter, Project Setup.
Navigate into the aem-guides-wknd
folder.
$ cd aem-guides-wknd
Build and deploy the project to a local instance of AEM with the following command:
$ mvn clean install -PautoInstallSinglePackage
If using AEM 6.5 or 6.4, append the classic
profile to any Maven commands.
$ mvn clean install -PautoInstallSinglePackage -Pclassic
Import the project into your preferred IDE by following the instructions to set up a local development environment.
Components can be thought of as small modular building blocks of a web page. In order to reuse components, the components must be configurable. This is accomplished via the author dialog. Next let’s author a simple component and inspect how values from the dialog are persisted in AEM.
Below are the high-level steps performed in the above video.
>
US >
en.cq:dialog
and helloworld.html
script from /apps/wknd/components/content/helloworld
.HTML Template Language or HTL is a light-weight, server-side templating language used by AEM components to render content.
Dialogs define the configurations available that can be made for a component.
Next let’s update the HelloWorld
HTL script to display an extra greeting before the text message.
Below are the high-level steps performed in the above video.
Switch to the IDE and open the project to the ui.apps
module.
Open the helloworld.html
file and update the HTML Markup.
Use the IDE tools like VSCode AEM Sync to synchronize the file change with the local AEM instance.
Return to the browser and observe the component render has changed.
Open the .content.xml
file that defines the dialog for the HelloWorld
component at:
<code>/aem-guides-wknd/ui.apps/src/main/content/jcr_root/apps/wknd/components/helloworld/_cq_dialog/.content.xml
Update the dialog to add an extra textfield named Title with a name of ./title
:
<?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="Properties"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./title"/>
<text
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Text"
name="./text"/>
</items>
</column>
</items>
</content>
</jcr:root>
Reopen the file helloworld.html
, which represents the main HTL script responsible for rendering the HelloWorld
component from below path:
<code>/aem-guides-wknd.ui.apps/src/main/content/jcr_root/apps/wknd/components/helloworld/helloworld.html
Update helloworld.html
to render the value of the Greeting textfield as part of an H1
tag:
<div class="cmp-helloworld" data-cmp-is="helloworld">
<h1 class="cmp-helloworld__title">${properties.title}</h1>
...
</div>
Deploy the changes to a local instance of AEM using the developer plugin or using your Maven skills.
Sling Models are annotation driven Java™ “POJOs” (Plain Old Java™ Objects) that facilitate the mapping of data from the JCR to Java™ variables. They also provide several other niceties when developing in the context of AEM.
Next, let’s make some updates to the HelloWorldModel
Sling Model in order to apply some business logic to the values stored in the JCR before outputting them to the page.
Open the file HelloWorldModel.java
, which is the Sling Model used with the HelloWorld
component.
<code>/aem-guides-wknd.core/src/main/java/com/adobe/aem/guides/wknd/core/models/HelloWorldModel.java
Add the following import statements:
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
Update the @Model
annotation to use a DefaultInjectionStrategy
:
@Model(adaptables = Resource.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class HelloWorldModel {
...
Add the following lines to the HelloWorldModel
class to map the values of the component’s JCR properties title
and text
to Java™ variables:
...
@Model(adaptables = Resource.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class HelloWorldModel {
...
@ValueMapValue
private String title;
@ValueMapValue
private String text;
@PostConstruct
protected void init() {
...
Add the following method getTitle()
to the HelloWorldModel
class, that returns the value of the property named title
. This method adds the additional logic to return a String value of “Default Value here!” if the property title
is null or blank:
/***
*
* @return the value of title, if null or blank returns "Default Value here!"
*/
public String getTitle() {
return StringUtils.isNotBlank(title) ? title : "Default Value here!";
}
Add the following method getText()
to the HelloWorldModel
class, that returns the value of the property named text
. This method transforms the String to all uppercase characters.
/***
*
* @return All caps variation of the text value
*/
public String getText() {
return StringUtils.isNotBlank(this.text) ? this.text.toUpperCase() : null;
}
Build and deploy the bundle from the core
module:
$ cd core
$ mvn clean install -PautoInstallBundle
For AEM 6.4/6.5 use mvn clean install -PautoInstallBundle -Pclassic
Update the file helloworld.html
at aem-guides-wknd.ui.apps/src/main/content/jcr_root/apps/wknd/components/content/helloworld/helloworld.html
to use the newly created methods of the HelloWorld
model:
<div class="cmp-helloworld" data-cmp-is="helloworld"
data-sly-use.model="com.adobe.aem.guides.wknd.core.models.HelloWorldModel">
<h1 class="cmp-helloworld__title">${model.title}</h1>
<div class="cmp-helloworld__item" data-sly-test="${properties.text}">
<p class="cmp-helloworld__item-label">Text property:</p>
<pre class="cmp-helloworld__item-output" data-cmp-hook-helloworld="property">${properties.text}</pre>
</div>
<div class="cmp-helloworld__item" data-sly-test="${model.text}">
<p class="cmp-helloworld__item-label">Sling Model getText() property:</p>
<pre class="cmp-helloworld__item-output" data-cmp-hook-helloworld="property">${model.text}</pre>
</div>
<div class="cmp-helloworld__item" data-sly-test="${model.message}">
<p class="cmp-helloworld__item-label">Model message:</p>
<pre class="cmp-helloworld__item-output"data-cmp-hook-helloworld="model">${model.message}</pre>
</div>
</div>
Deploy the changes to a local instance of AEM using the Eclipse Developer plugin or using your Maven skills.
Client-Side Libraries, clientlibs
for short, provides a mechanism to organize and manage CSS and JavaScript files necessary for an AEM Sites implementation. Client-side libraries are the standard way to include CSS and JavaScript on a page in AEM.
The ui.frontend module is a de-coupled webpack project that is integrated into the build process. This enables the use of popular front-end libraries like Sass, LESS, and TypeScript. The ui.frontend
module is explored in more depth in the Client-Side Libraries chapter.
Next, update the CSS styles for the HelloWorld
component.
Below are the high-level steps performed in the above video.
Open a terminal window and navigate into the ui.frontend
directory
Being in ui.frontend
directory run the npm install npm-run-all --save-dev
command to install the npm-run-all node module. This step is required on Archetype 39 generated AEM project, in upcoming Archetype version this is not required.
Next, run the npm run watch
command:
$ npm run watch
Switch to the IDE and open the project to the ui.frontend
module.
Open the file ui.frontend/src/main/webpack/components/_helloworld.scss
.
Update the file to display a red title:
.cmp-helloworld {}
.cmp-helloworld__title {
color: red;
}
In the terminal, you should see activity indicating that the ui.frontend
module is compiling and syncing the changes with the local instance of AEM.
Entrypoint site 214 KiB = clientlib-site/site.css 8.45 KiB clientlib-site/site.js 206 KiB
2022-02-22 17:28:51: webpack 5.69.1 compiled successfully in 119 ms
change:dist/index.html
+ jcr_root/apps/wknd/clientlibs/clientlib-site/css/site.css
+ jcr_root/apps/wknd/clientlibs/clientlib-site/css
+ jcr_root/apps/wknd/clientlibs/clientlib-site/js/site.js
+ jcr_root/apps/wknd/clientlibs/clientlib-site/js
+ jcr_root/apps/wknd/clientlibs/clientlib-site
+ jcr_root/apps/wknd/clientlibs/clientlib-dependencies/css.txt
+ jcr_root/apps/wknd/clientlibs/clientlib-dependencies/js.txt
+ jcr_root/apps/wknd/clientlibs/clientlib-dependencies
Return to the browser and observe that the title color has changed.
Congratulations, you have learned the basics of component development in Adobe Experience Manager!
Get familiar with Adobe Experience Manager pages and templates in the next chapter Pages and Templates. Understand how Core Components are proxied into the project and learn advanced policy configurations of editable templates to build out a well-structured Article Page template.
View the finished code on GitHub or review and deploy the code locally at on the Git branch tutorial/component-basics-solution
.