ADOBE EXPERIENCE MANAGER (AEM) COMPONENTS

Button Component

An Adobe Experience Manager (AEM) example to demonstrate development of extending the core button component to allow an image to be added from the AEM Digital Asset Manager (DAM) and an option to open a button link in a new tab.

Getting Started

As a best practice for AEM projects, we’re using a Maven project archetype for this. Since we’re not modifying or creating any Java classes for this, you could develop the component directly in CRXDE Lite if you prefer, but this is not recommended.

Button Component

Copy the core button component template into your projects button component folder.

Core button component template: /apps/core/wcm/components/button/v1/button/button.html

Using git, clone the aem-core-wcm-components repo onto your local computer to inspect and copy its source into your project as needed.

In our copy of the button template, update the path to use the core component icon template since we’re not copying or modifying icon.html. e.g.,

button.html
...
<button data-sly-use.button="com.adobe.cq.wcm.core.components.models.Button"
        data-sly-use.component="com.adobe.cq.wcm.core.components.models.Component"
        data-sly-use.iconTemplate="/apps/core/wcm/components/button/v1/button/icon.html"
        ...
        >
...
</button>

Note that the ellipsis ... in the code snippet above is not a part of the actual code and is there only to denote code that is being skipped and not applicable to the example.

Before we begin to modify the button component, deploy the updated button.html to your AEM server to verify that it is working on a page. If needed, the code deployment page has more information on how to deploy code to your AEM server.

Image Tab

The first modification we will make is the addition of an image tab in the button dialog to allow an author to add an image from the DAM that will render within the button components element.

In order to modify the dialog we need to copy it from the core button component. For this step, I will copy the button/_cq_dialog folder from the aem-core-wcm-components repo source into my project. You could copy the respective /apps/core/wcm/components/button/v1/button/cq:dialog and paste it into your projects button component within AEM using CRX/DE if you prefer, but I find it easier to work with and maintain on my local file system. For example, using CRX/DE to edit the cq:dialog and add the image tab, nodes and properties is not the same as opening button/_cq_dialog/.content.xml in your code editor.

In this example, I will copy the _cq_dialog folder from the aem-core-wcm-components repo and paste it into ui.apps/.../jcr_root/apps/myproject/components/button/

After the accessibility node, insert the following image node in our copy of the dialog .content.xml.

_cq_dialog/.content.xml
...
<image
    jcr:primaryType="nt:unstructured"
    jcr:title="Image"
    sling:resourceType="granite/ui/components/coral/foundation/container"
    margin="{Boolean}true">
    <items jcr:primaryType="nt:unstructured">
        <columns
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
            margin="{Boolean}true">
            <items jcr:primaryType="nt:unstructured">
                <column
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/container">
                    <items jcr:primaryType="nt:unstructured">
                        <fileupload
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
                            allowUpload="{Boolean}false"
                            autoStart="{Boolean}false"
                            class="cq-droptarget"
                            fieldLabel="Image"
                            fileNameParameter="./fileName"
                            fileReferenceParameter="./fileReference"
                            mimeTypes="[image/gif,image/jpeg,image/png,image/webp,image/svg+xml]"
                            multiple="{Boolean}false"
                            name="./fileName"
                            title="Upload an image asset:"
                            uploadUrl="${suffix.path}"
                            useHTML5="{Boolean}true"/>
                        <altText
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                            fieldDescription="The alt text attribute value for the image."
                            fieldLabel="Alt Text"
                            name="./altText"/>
                    </items>
                </column>
            </items>
        </columns>
    </items>
</image>
...

For the image to render, we need to update our button.html. e.g.,

after

<sly data-sly-call="${iconTemplate.icon @ icon=button.icon}"></sly>

add

<span data-sly-test="${properties.fileReference}"
      class="cmp-button-img">
    <img src="${properties.fileReference}"
         alt="${properties.alt}"/>
</span>

Deploy the updated button component to the AEM server.

Using the updated dialog, add an image from the DAM to verify that it is working.

AEM Button Component with Image Demo of button component extended to allow an image from the DAM to be shown.

In this step, we’re adding a switch to the dialog form to allow an author to choose to open button links in a new tab or window.

After the link node in the properties tab, insert the following linkTarget node in our button component dialog .content.xml.

_cq_dialog/.content.xml
...
<linkTarget
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/switch"
    fieldLabel="Open the link in a new tab or window?"
    name="./linkTarget"
    uncheckedValue="{Boolean}false"
    value="{Boolean}true"/>
...

At the very top of template, above the button element, add the following sightly expression to set a linkTarget variable.

button.html
<sly data-sly-set.linkTarget="${properties.link && properties.linkTarget == 'true' ? '_blank' : ''}"/>
...

When the switch to open button link in new tab is on, as a best practice, we’re adding the rel="noopener" attribute to the link in addition to the target="_blank" attribute.

In button element, below the href attribute, add the rel and target attributes. These attributes will only be rendered if they are not empty.

button.html
...
<button data-sly-use.button="com.adobe.cq.wcm.core.components.models.Button"
        data-sly-use.component="com.adobe.cq.wcm.core.components.models.Component"
        data-sly-use.iconTemplate="/apps/core/wcm/components/button/v1/button/icon.html"
        data-sly-element="${button.link ? 'a' : 'button'}"
        type="${button.link ? '' : 'button'}"
        id="${component.id}"
        class="cmp-button"
        href="${button.link}"
        rel="${linkTarget == '_blank' ? 'noopener' : ''}"
        target="${linkTarget}"
        aria-label="${button.accessibilityLabel}"
        data-cmp-clickable="${button.data ? true : false}"
        data-cmp-data-layer="${button.data.json}">
...
</button>

Deploy the updated button component to the AEM server.

Using the updated dialog, add a link and test it with and without the switch set to open the link in a new tab or window to verify that it is working.

AEM Button Component with Link Target Switch Demo of button component extended with a switch to toggle open link in a new tab.


Source Code

Part 4 of 5 in the AEM Component Dev series.

Part 1 | Message Component | Multifield Component

comments powered by Disqus