AEM components are used to hold, format, and render the content made available on your webpages.
When authoring pages, the components allow the authors to edit and configure the content.
When constructing a Commerce site the components can, for example, collect and render information from the catalog.
See Developing eCommerce for more information.
When constructing a Communities site the components can provide information to and collect information from your visitors.
See Developing Communities for more information.
On the publish instance, the components render your content, presenting it as you require to your website visitors.
This page is a continuation of the document AEM Components - The Basics.
Components below /libs/cq/gui/components/authoring/dialog
are meant to be used only in the Editor (component dialogs in Authoring). If they are used elsewhere (such as in a wizard dialog for instance), they may not behave as expected.
This page provides the reference documentation (or links to reference documentation) required to develop new components for AEM. See Developing AEM Components - Code Samples for some practical examples.
The basic structure of a component is covered on the page AEM Components - The Basics. That document covers both the touch-enabled and classic UIs. Even if you do not need to use the classic settings in your new component it can help to be aware of them when inheriting from existing components.
Depending on the component you want to implement, it might be possible to extend or customize an existing instance, rather than defining and developing the entire structure from scratch.
When extending or customizing an existing component or dialog, you can copy or replicate either the entire structure or the structure required for the dialog before making your changes.
Extending an existing component can be achieved with Resource Type Hierarchy and the related inheritance mechanisms.
Components can also be redefined with an overlay based on the search path logic. However, in such case, the Sling Resource Merger is not triggered and /apps
must define the entire overlay.
The content fragment component can also be customized and extended, though the full structure and relationships with Assets must be considered.
It is also possible to override a component dialog using the Sling Resource Merger and defining the property sling:resourceSuperType
.
This means you only need to redefine the required differences, as opposed to redefining the entire dialog (using sling:resourceSuperType
). This is now recommended method for extending a component dialog
See the Sling Resource Merger for more details.
Your component will be rendered with HTML. Your component needs to define the HTML needed to take the required content and then render it as required, on both the author and publish environments.
The HTML Templating Language (HTL), introduced with AEM 6.0, takes the place of JSP (JavaServer Pages) as the preferred and recommended server-side template system for HTML. For web developers who need to build robust enterprise websites, HTL helps to achieve increased security and development efficiency.
Although both HTL and JSP can be used for developing components, we will illustrate development with HTL on this page, as it is the recommended scripting language for AEM.
This optional logic selects and/or computes the content to be rendered. It is invoked from HTL expressions with the appropriate Use-API pattern.
The mechanism to separate logic from appearance helps clarify what is called for a given view. It also allows differing logic for different views of the same resource.
The HTL Java Use-API enables a HTL file to access helper methods in a custom Java class. This lets you use Java code to implement the logic for selecting and configuring the component content.
The HTL JavaScript Use-API enables a HTL file to access helper code written in JavaScript. This allows you to use JavaScript code to implement the logic for selecting and configuring the component content.
Modern websites rely heavily on client-side processing driven by complex JavaScript and CSS code. Organizing and optimizing the serving of this code can be a complicated issue.
To help deal with this issue, AEM provides Client-side Library Folders, which allow you to store your client-side code in the repository, organize it into categories and define when and how each category of code is to be served to the client. The client-side library system then takes care of producing the correct links in your final web page to load the correct code.
Read Using Client-Side HTML Libraries for more information.
You can configure the edit behavior of a component including attributes such as actions available for the component, characteristics of the inplace editor, and the listeners related to events on the component. The configuration is common to both the touch-enabled and classic UI, albeit with certain, specific differences.
The edit behavior of a component is configured by adding a cq:editConfig
node of type cq:EditConfig
below the component node (of type cq:Component
) and by adding specific properties and child nodes.
The WCM Mode cookie is set when switching to Preview mode even when the page is not refreshed.
For components with a rendering that are sensitive to the WCM Mode, they need to be defined to refresh themselves specifically, then rely on the value of the cookie.
In the touch-enabeld UI only the values EDIT
and PREVIEW
are used for the WCM Mode cookie.
Dialogs are used to allow author to interact with the component. Using a dialog allows authors and/or administrators to edit content, configure the component or define design parameters (using a Design Dialog)
Coral UI and Granite UI define the modern look and feel of AEM.
Granite UI provides a large range of the basic components (widgets) needed to create your dialog on the authoring environment. When necessary you can extend this selection and create your own widget.
For full details see:
Coral UI
Granite UI
Due to the nature of the Granite UI components (and differences to the ExtJS widgets), there are some differences between how components interact with the touch-enabled UI and the classic UI.
Dialogs for the touch-enabled UI:
are named cq:dialog
.
are defined as an nt:unstructured
node with the sling:resourceType
property set.
are located under their cq:Component
node and next to their component definition.
are rendered on the server-side (as Sling components), based on their content structure and the sling:resourceType
property.
use the Granite UI framework.
contain a node structure describing the fields within the dialog.
nt:unstructured
with the required sling:resourceType
property.An example node structure might be:
newComponent (cq:Component)
cq:dialog (nt:unstructured)
content
layout
items
column
items
file
description
Customizing a dialog is similar to developing a component as the dialog is itself a component (i.e. markup rendered by a component script together with behavior/style provided by a client library).
For examples, see:
/libs/foundation/components/text/cq:dialog
/libs/foundation/components/download/cq:dialog
If a component has no dialog defined for the touch-enabled UI, then the classic UI dialog is used as a fallback inside of a compatibility layer. To customize such a dialog you need to customize the classic UI dialog. See AEM Components for the Classic UI.
See:
Widgets for the touch-enabled UI are implemented as Granite UI components.
To create a new widget for use in a component dialog for the touch-enabled UI requires you to create a new Granite UI field component.
For full details about the Granite UI, please see the Granite UI documentation.
If you consider your dialog as a simple container for a form element, then you can also see the primary content of your dialog content as form fields. Creating a new form field requires you to create a resource type; this is equivalent to creating a new component. To help you in that task, Granite UI offers a generic field component to inherit from (using sling:resourceSuperType
):
/libs/granite/ui/components/coral/foundation/form/field
More specifically Granite UI provides a range of field components that are suitable for use in dialogs (or, more generally speaking, in forms).
This differs from the classic UI, where widgets are represented by cq:Widgets
nodes, each with a particular xtype
to establish the relation with their corresponding ExtJS widget. From an implementation viewpoint, these widgets were rendered on the client-side by the ExtJS framework.
Once you have created your resource type, you can instantiate your field by adding a new node in your dialog, with the property sling:resourceType
referring to the resource type you have just introduced.
If you want to define styling and behavior for your component, you can create a dedicated client library that defines your custom CSS/LESS and JS.
To have your client library loaded solely for your component dialog (i.e. it will not be loaded for another component) you need to set the property extraClientlibs
** **of your dialog to the category name of the client library you have just created. This is advisable if your client library is quite big and/or your field is specific to that dialog and will not be needed in other dialogs.
To have your client library loaded for all dialogs, set the category property of your client library to cq.authoring.dialog
. This is the category name of the client library that is included by default when rendering all dialogs. You want to do that if you client library is small and/or your field is generic and could be reused in other dialogs.
For an example, see:
cqgems/customizingfield/components/colorpicker/clientlibs
Depending on your requirements, you can either:
sling:resourceSuperType
)You can also use render conditions ( rendercondition
) to control who has access to specific tabs/fields in your dialog; for example:
+ mybutton
- sling:resourceType = granite/ui/components/coral/foundation/button
+ rendercondition
- sling:resourceType = myapp/components/renderconditions/group
- groups = ["administrators"]
The method of handling events on dialog fields is now done with listeners in a custom client library. This is a change from the older method of having listeners in the content structure.
To inject logic into your field, you should:
To achieve this you need to know about the underlying widget library with which you want to interact. See the Coral UI documentation to identify to which event you want to react. This is very similar to the process that you had to perform with ExtJS in the past: find the documentation page of a given widget, then check the details of its event API.
For an example, see:
cqgems/customizingfield/components/clientlibs/customizingfield
In the classic UI with ExtJS, it was usual to have listeners for a given widget in the content structure. Achieving the same in the touch-enabled UI is different as JS listener code (or any code at all) is no longer defined in the content.
The content structure describes the semantic structure; it should (must) not imply the nature of the underlying widget. By not having JS code in the content structure, you can change the implementation details without having to change the content structure. In other words, you can change the widget library without needing to touch the content structure.
If you have a custom JavaScript that needs to be executed only when the dialog is available and ready, you should listen for the dialog-ready
event.
This event is triggered whenever the dialog loads (or re-loads) and is ready for use, which means whenever there is a change (create/update) in the DOM of the dialog.
dialog-ready
can be used to hook in JavaScript custom code that performs customizations on the fields inside a dialog or similar tasks.
To mark a given field as mandatory set the following property on the content node of your field:
required
Boolean
For an example, see:
/libs/foundation/components/page/cq:dialog/content/items/tabs/items/basic/items/column/items/title/items/title
Field validation in Granite UI and the Granite UI Components (equivalent to widgets), is done by using the foundation-validation
API. See the foundation-valdiation
Granite documentation for details.
For examples, see:
cqgems/customizingfield/components/clientlibs/customizingfield/js/validations.js
/libs/cq/gui/components/authoring/dialog/clientlibs/dialog/js/validations.js
The Design dialog is provided when a component has design details that can be edited in Design Mode.
The definition is very similar to that of a dialog used for editing content, with the difference that it is defined as a node:
cq:design_dialog
nt:unstructured
An inplace editor allows the user to edit content directly in the paragraph flow, without the need to open a dialog. For example, the standard Text and Title components both have an inplace editor.
An inplace editor is not necessary/meaningful for every component type.
See Extending Page Authoring - Add New Inplace Editor for more information.
The Component Toolbar gives the user access to a range of actions for the component such as edit, configure, copy, and delete.
See Extending Page Authoring - Add New Action to a Component Toolbar for more information.
If your new component references content from other pages then you can consider whether you want it to impact the Borrowed Content and Lent Content sections of the References Rail.
Out-of-the-box AEM only checks the Reference component. To add your component you need to configure the OSGi bundle WCM Authoring Content Reference Configuration.
Create a new entry in the definition, specifying your component, together with the property to be checked. For example:
/apps/<*your-Project*>/components/reference@parentPath
When working with AEM there are several methods of managing the configuration settings for such services. See Configuring OSGi for more details and the recommended practices.
After the component has been developed it needs to be enabled for use in an appropriate paragraph system, so it can be used on the required pages.
This can be done by either:
components
property on the paragraph system of a template.AEM offers the possibility to configure a paragraph system on your page so that an instance of your new component is automatically created when a user drags an (appropriate) asset onto an instance of that page (instead of always having to drag an empty component to the page).
This behavior, and the required asset-to-component relationship can be configured:
Under the paragraph definition of your page design. For example:
/etc/designs/<myApp>/page/par
Create a new node:
cq:authoring
nt:unstructured
Under this create a new node to hold all the asset-to-component mappings:
assetToComponentMapping
nt:unstructured
For each asset-to-component mapping create a node:
nt:unstructured
Each with the following properties:
assetGroup
:
String
media
assetMimetype
:
String
image/*
droptarget
:
String
image
resourceType
:
String
foundation/components/image
type
:
String
Images
For examples see:
/etc/designs/geometrixx/jcr:content/page/par/cq:authoring
/etc/designs/geometrixx-outdoors/jcr:content/page/par/cq:authoring
/etc/designs/geometrixx-media/jcr:content/article/article-content-par/cq:authoring
CODE ON GITHUB
You can find the code of this page on GitHub
The automatic creation of component instances can now be configured easily within the UI when using Core Components and Editable Templates. See Creating Page Templates for more information about defining which components are automatically associated with given media types.
The AEM Brackets Extension provides a smooth workflow to edit AEM components and client libraries. It is based on the Brackets code editor.
The extension:
Brackets is the recommended mechanism for creating components. It replaces the CRXDE Lite - Create Component functionality, which was designed for the classic UI.
When migrating a component that was designed for use with the classic UI to a component that can be used with the touch-enabled UI (either solely or jointly) the following issues should be considered:
HTL
Components
cq:listener
code that use classic UI specific functionscq:listener
code that uses functions specific to the classic UIDialogs
If you are migrating a project that was designed for the classic UI, then the cq:listener
code (and component related clientlibs) might use functions that are specific to the classic UI (such as CQ.wcm.*
). For the migration you must update such code using the equivalent objects/functions in the touch-enabled UI.
If your project is being completely migrated to the touch-enabled UI you need to replace such code to use the objects and functions relevant to the touch-enabled UI.
However, if your project must cater for both the classic UI and the touch-enabled UI during the migration period (the usual scenario), then you must implement a switch to differentiate the separate code referencing the appropriate objects.
This switch mechanism can be implemented as:
if (Granite.author) {
// touch UI
} else {
// classic UI
}
As a developer, you want easy access to component documentation so that you can quickly understand:
For this reason, it is easy to make any existing documentation markdown you have available within the component itself.
Place a README.md
file in the component structure. This markdown is displayed in the component console.
The supported markdown is the same as that for content fragments.