May 10, 2020
Estimated Post Reading Time ~

Automatically set properties in AEM

In this article, I will describe how the properties of a component can be set automatically when they are dropped into a parsys or a responsive grid, with two different approaches. The first approach only supports static values where the second supports both static and dynamic values.
The simple case

AEM comes with a really cool feature that allows developers to get it working right away, the only thing to do is simply add a node called "cq:template" of type "nt:unstructured" directly under the component node, and fill it with the properties and values to be set.

Let’s work on an example:

First, create a simple component. In this case, I am just going to extend the text component of core components:

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
componentGroup="demo"
jcr:title="Text 2"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>

Now, I just need to add the "cq:template" node directly under the component’s node:

And fill it in with the properties I want to set automatically:

<jcr:root 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"
text="Static text via cq:template"
textIsRich="true"/>

Now, it's ready to be tested – let's see how it works:

As this AEM feature is powered by the @copyFrom feature of Sling POST servlet (official documentation), only static properties values can be set.
I need more!

Often, the "cq:template" approach is not enough. Why? Because some scenarios require the components to be initialized with values depending on the page, the user or whatever other non-static value according to business needs.

How can I accomplish that?
AEM Components usually have an edit configuration node of type "cq:EditConfig" - under this configuration node, where listeners can be defined. A commonly used one is to have afterinsert="REFRESH_PAGE", if the page needs to be refreshed when the component is dropped.

Listeners support predefined constants, but they also allow developers to include Javascript code. So, I will use this feature to leverage the dynamic configuration of components.

Let’s create a new component to show how it works.

As I did in the previous example, I will extend the text component of core components:

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
componentGroup="demo"
jcr:title="Text 2"
sling:resourceSuperType="core/wcm/components/text/v2/text"/>

Now, I will create a clientlib to contain our function, using one of the AEM hooks to extend the pages editor capabilities:

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
categories="[cq.authoring.editor.sites.page.hook]"/>
Then, I can create the javascript file with the function itself:

;(function (ns) {
'use strict';
ns.demo2 = ns.demo2 || {};
ns.demo2.afterinsert = function (component) {
var text = '<h2>Dynamic text</h2>';
text += '<p><b>This is a dynamic text evaluated when the component is dropped</b></p>';
text += '<p><b>Page path</b>: ' + ns.page.path + '</p>';
text += '<p><b>Date</b>: ' + new Date() + '</p>';
ns.editableHelper.doUpdate(component, {
text: text,
textIsRich: 'true'
});
component.refresh();
};
}(Granite.author));

In this example, the dynamic content to set includes the current path of the page where the component is dropped and the current date and time.

As you can see on line 6, I am adding the "afterinsert" function to "Granite.author", under the "demo2" namespace.

Line 11 is where the magic happens. The "doUpdate" function on editable helper allows the component to be updated via Javascript code, passing as a parameter a JSON object with the data to be set in the component’s properties (internally, it does an Ajax POST with the properties as payload).

In line 15, the "refresh" method causes the UI to be updated to reflect the changes.

Now, the only pending thing to make it work, is to add the "cq:editConfig" node to the component, with the Javascript call on "afterinsert" listener:

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:EditConfig">
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
afterinsert="function () {Granite.author.demo2.afterinsert(this);}"/>
</jcr:root>
The complete structure of the solution should then look like this:

Now, the second text component is ready to be tested – let's see how it works:

Source: https://www.linkedin.com/pulse/aem-automatically-set-properties-nestor-de-dios


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.