You're viewing help content for version:
- 6.2
- Older Versions
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.
- When constructing a Commerce site the components can, for example, collect and render information from the catalog.
- On the publish instance the components render your content, presenting it as you require to your website visitors.
Note:
This page is an extension to AEM Components - the Basics.
Caution:
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 the touch-optimized UI. See Developing AEM Components for the Touch-Optimized UI - Code Samples for some practical examples.
The basic structure of a component is covered on the page AEM Components - the Basics. This section covers both the touch-optimized 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 customing 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.
Note:
Components can also be redefined with an overlay based on the search path logic; but in such case, the Sling Resource Merger will not be triggered and /apps must define the entire overlay.
Note:
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 (Hyper Text Markup Language). Your component needs to define the HTML needed to take the required content 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, the HTML Template Language helps to achieve increased security and development efficiency.
Note:
Although both HTL and JSP can be used for developing components for the touch-optimized UI, 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 allows you to 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; this includes 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-optimized 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 in the touch-optimized UI; 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.
Note:
In the touch-optimized 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)
The touch-optimized UI uses Coral UI and Granite UI for the look-and-feel.
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
- Provides a consistent UI across all cloud solutions
- Concepts of the AEM Touch-Optimized UI - Coral UI
- Coral UI Guide
- Provides a consistent UI across all cloud solutions
- Granite UI
- Provides Coral UI markup wrapped into Sling components for building UI consoles and dialogs
- Concepts of the AEM Touch-Optimized UI - Granite UI
- Granite UI Documentation
- Provides Coral UI markup wrapped into Sling components for building UI consoles and dialogs
Note:
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-optimized UI and the classic UI.
Dialogs for the touch-optimized 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.
- these nodes are nt:unstructured with the required sling:resourceType property.
- these nodes are nt:unstructured with the required sling:resourceType property.
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
Note:
If a component has no dialog defined for the touch-optimized UI, then the classic UI dialog is used as a fallback inside a compatibility layer. To customize such a dialog you need to customize the classic UI dialog. See AEM Components for the Classic UI.
Note:
See:
- the AEM Gems session on Customizing Dialog Fields.
- the related sample code covered under Code Sample - How to Customize Dialog Fields.
To create a new widget for use in a component dialog for the touch-optimized UI, therefore requires you to create a new Granite UI field component.
Note:
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/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).
Note:
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.
Note:
Such components are still written in JSP and not in HTL, because form fields are a special case. This is because they rely heavily on passing values from one script to another through the request, an action that is not possible in HTL (at the moment). Therefore, form fields (as an exception) should still be written in JSP.
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
- provided by the Code Sample
Depending on your requirements, you can either:
- Extend a given Granite UI field by component inheritance (sling:resourceSuperType)
- Extend a given widget from the underlying widget library (in the case of Granite UI, this is Coral UI), by following the widget library API (JS/CSS inheritance)
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/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 (touch-optimized UI). This is a change from the older method of having listeners in the content structure (classic UI with ExtJS).
To inject logic into your field, you should:
- Have your field marked with a given CSS class (the hook).
- Define, in your client library a JS listener hooked on that CSS class name (this ensures that your custom logic is scoped to your field only, and does not affect other fields of the same type).
To achieve this you need to know about the underlying widget library that you want to interact with; see the Coral UI documentation to identify which event you want to react on (this is very similar to the process that you had to perform with ExtJS: 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
- provided by the Code Sample
In the classic UI with ExtJS, it was usual to have listeners for a given widget in the content structure. Achieving the same in Touch 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.
To mark a given field as mandatory set the following property on the content node of your field:
- Name: required
- Type: Boolean
/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
- provided by the Code Sample
- /etc/scaffolding/geometrixx-outdoors/clientlibs-touch/validators.js
- /libs/cq/gui/components/authoring/dialog/clientlibs/dialog/js/validations.js
Note:
A comparable example for the classic UI can be seen at:
/etc/scaffolding/geometrixx-outdoors/clientlibs-classic/validators.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:
- Node name: cq:design_dialog
- Type: 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; for example, edit, configure, copy, 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
Note:
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:
- using Design mode when editing a specific page.
- defining the 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).
-
For each asset-to-component mapping create a node:
- Name: text; it is recommended that the name indicate the asset and related component type; for example, image
- Type: nt:unstructured
Each with the following properties:
- assetGroup:
- Type: String
- Value: the group that the related asset belongs to; for example, media
- assetMimetype:
- Type: String
- Value: the mime type of the related asset; for example image/*
- droptarget:
- Type: String
- Value: the drop target; for example, image
- resourceType:
- Type: String
- Value: the related component resource; for example, foundation/components/image
- type:
- Type: String
- Value: the type, for example, Images
- Name: text; it is recommended that the name indicate the asset and related component type; for example, image
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
- Open aem-project-archetype project on GitHub
- Download the project as a ZIP file
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:
- eases synchronization (no Maven or File Vault required) to help increase developer efficiency and also helps front-end developers with limited AEM knowledge to participate on projects.
- provides some HTL support, the template language designed to simplify component development and increase security.
Note:
Brackets is the recommended mechanism for creating components for the touch-optimized UI. 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-optimized UI (either solely or jointly) the following issues should be considered:
- HTL
- Use of HTL is not compulsory for the touch-optimized UI, but if your component needs updating then it is an ideal time to consider migrating from JSP to HTL.
- Use of HTL is not compulsory for the touch-optimized UI, but if your component needs updating then it is an ideal time to consider migrating from JSP to HTL.
- Components
- Migrate cq:listener code that use classic UI specific functions
- RTE plugin; for further information see Configuring the Rich Text Editor.
- Migrate cq:listener code that uses functions specific to the classic UI
- Dialogs
- You will need to create a new dialog for use in the touch-optimized UI. However, for compatibility purposes the touch-optimized UI can use the definition of a classic UI dialog, when no dialog has been defined for the touch-optimized UI.
- The Dialog Conversion Tool is provided to help you extend existing components.
- Mapping ExtJS to Granite UI Components provides a convenient overview of ExtJS xtypes and node types with their equivalent Granite UI resource types.
- Customizing fields; for more information see the AEM Gems session on Customizing Dialog Fields.
- Migrate from vtypes to Granite UI validation
- Using JS listeners; for more information see Handling Field Events and the AEM Gems session on Customizing Dialog Fields.
- You will need to create a new dialog for use in the touch-optimized UI. However, for compatibility purposes the touch-optimized UI can use the definition of a classic UI dialog, when no dialog has been defined for the touch-optimized UI.
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 for the touch-optimized UI.
If your project is being completely migrated to the touch-optimized UI you need to replace such code to use the objects and functions relevant to the touch-optimized UI.
However, if your project must cater for both the classic UI and the touch-optimized UI during the migration period (the usual scenario), then you need to implement a switch to differentiate the separate code referencing the appropriate objects.
if (Granite.author) { // touch UI } else { // classic UI }