Customization Patterns
Customizing Dialogs
It may be desired to customize the configuration options available in a core component dialog, be it the Design Dialog or the Edit Dialog.
Each dialog has a consistent node structure. It is recommended that this structure is replicated in an inheriting component so that Sling Resource Merger and Hide Conditions can be used to hide, replace, or reorder sections of the original dialog. The structure to replicate is defined as anything up to the tab item node level.
To be fully compatible with any changes made to a dialog on its current version, it is very important that structures below the tab item level not be touched (hidden, added to, replaced, reordered, etc.). Instead, a tab item from the parent should be hidden via the sling:hideResource
property (see Sling Resource Merger Properties), and new tab items added that contain the bespoke configuration fields. sling:orderBefore
can be used to reorder tab items if necessary.
The dialog below demonstrates the recommended dialog structure as well as how to hide and replace an inherited tab as described above:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="https://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="https://www.jcp.org/jcr/1.0"
xmlns:nt="https://www.jcp.org/jcr/nt/1.0"
xmlns:granite="https://www.adobe.com/jcr/granite/1.0"
jcr:primaryType="nt:unstructured">
<content jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<tabs jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<originalTab
jcr:primaryType="nt:unstructured"
sling:hideResource="true"/>
<myTab
jcr:primaryType="nt:unstructured"
jcr:title="My Tab"
sling:resourceType="granite/ui/components/coral/foundation/container">
<!-- myTab content -->
</myTab>
</items>
</tabs>
</items>
</content>
</jcr:root>
Customizing the Logic of a Core Component
The Business logic for the core components is implemented in Sling Models. This logic can be extended by using a Sling delegation pattern.
For example, the title core component uses the jcr:title
property of the requested resource to provide the title text. If no jcr:title
property is defined, a fallback to the current page title is implemented. We want to change the behavior so that the title of the current page is always displayed.
Because the implementation of the Core Components’ models are private, they must be extended with a delegation pattern.
@Model(adaptables = SlingHttpServletRequest.class,
adapters = Title.class,
resourceType = "myproject/components/pageHeadline")
public class PageHeadline implements Title {
@ScriptVariable private Page currentPage;
@Self @Via(type = ResourceSuperType.class)
private Title title;
@Override public String getText() {
return currentPage.getTitle();
}
@Override public String getType() {
return title.getType();
}
}
For further details about the delegation pattern see the Core Components GitHub Wiki article Delegation Pattern for Sling Models.
Customizing the Markup
Sometimes advanced styling requires a different markup structure of the component.
This can easily be done by copying the HTL files that need to be modified from the Core Component into the proxy component.
Taking again the example of the Core Breadcrumb Component, to customize its markup output, the breadcrumb.html
file would have to be copied into the site-specific component that has a sling:resourceSuperTypes
that points to the Core Breadcrumb Component.
Styling the Components
The first form of customization is to apply CSS styles.
To make this easy, the Core Components render semantic markup and follow a standardized naming convention inspired by Bootstrap. Also, to easily target and namespace the styles for the individual components, each Core Component is wrapped in a DIV element with the " cmp
" and " cmp-<name>
" classes.
For instance, looking at the HTL file of the v1 Core Breadcrumb Component: breadcrumb.html, we see that the hierarchy of elements output are ol.breadcrumb > li.breadcrumb-item > a
. So to make sure that a CSS rule only affects the breadcrumb class of that component, all rules should be namespaced as shown below:
.cmp-breadcrumb .breadcrumb {}
.cmp-breadcrumb .breadcrumb-item {}
.cmp-breadcrumb a {}
Additionally, each of the Core Components leverage the AEM Style System feature that allows template authors to define additional CSS class names that can be applied to the component by the page authors. This allows to define for each template a list of allowed component styles, and whether one of them should apply by default to all components of that kind.
Upgrade Compatibility of Customizations
Three different kind of upgrades are possible:
- upgrading the version of AEM
- upgrading the Core Components to a new minor version
- upgrading the Core Components to a major version
Generally, upgrading AEM to a new version won’t impact the Core Components or the customizations done, provided that the components’ versions also support the new AEM version that is being migrated to, and that customizations don’t use APIs that have been deprecated or removed.
Upgrading the Core Components without switching to a newer major version shouldn’t affect customizations, as long as the customization patterns described on this page are used.
Switching to a newer major version of the Core Components is compatible only for the content structure, but customizations may need to be refactored. Clear change logs will be published for each component version to highlight the changes that would impact the kind of customizations described on this page.