Hai Hoang
Hai Hoang

Reputation: 1257

How can I inherit page properties in AEM 6.2?

In our AEM 6.2 project, I ran to a scenario where I need to config a navigation in one page (let call this Homepage), all of the other pages can use home navigation config or use their own navigation config values.

I decided to use live copy because the clone pages can cancel the linked properties at any time and use their own values. But there is two problem with this approach:

  1. Users must set the template for clone pages by edit their jcr: content/sling:resourceType and jcr: content/cq: template because the navigation is used in all pages and our web uses about 5+ templates.
  2. Live copy does no allowed clone pages are children of source pages. But I was required to make web structure like this :

    Home
       |_ Page 1
                |_ Page 1.1
       |_ Page 2
       |_ Page 3
    

Live copy maybe not suitable for this situation, we change to use HTL ${inheritedPageProperties}, this solve the template and structure issue but it creates two new problems:

  1. Inherited properties in property config dialog of child page will be blank (because they are not set and called via ${inheritedPageProperties} )

  2. If users change properties in "Page 1" page, "Page 1.1" (and Page 1.1.1, etc ...) will use these values (Because ${inheritedPageProperties} search the upper nodes to get value).

What our client want are :

How can I achieve these requirements?

Upvotes: 3

Views: 6893

Answers (1)

Ahmed Musallam
Ahmed Musallam

Reputation: 9753

You can achieve this with a simple Sling Model and Sling's CompositeValueMap

CompositeValueMap docs state:

An implementation of the ValueMap based on two ValueMaps: - One containing the properties - Another one containing the defaults to use in case the properties map does not contain the values. In case you would like to avoid duplicating properties on multiple resources, you can use a CompositeValueMap to get a concatenated map of properties.

We can use this by supplying the descendant's value map (the current page's) then finding the correct ancestor and supplying its properties valuemap as the defaults.

for the purposes of this question, I always assume that 2rd descendant from root is always the ancestor (you can find your ancestor according to your requirnments)

package com.sample.helpers;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.CompositeValueMap;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.Self;

import javax.annotation.PostConstruct;

@Model(adaptables = Resource.class)
public class CustomInheritedPageProperties
{

    ValueMap inheritedProperties;

    @Self
    Resource currentResource;

    @OSGiService
    PageManager pageManager;

    @PostConstruct
    protected void init() {
        // get the current page, or the "descendant"
        Page descendant = pageManager.getContainingPage(currentResource);

        /* You have to add your custom logic to get the ancestor page.
         * for this question's purposes, I'm always assuming it's the 3rd decendant of root
         * more here: https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/javadoc/com/day/cq/wcm/api/Page.html#getParent(int)
         */
        Page ancestor = descendant.getParent(2);

        // create a CompositeValueMap where the properties are descendant's and the defaults are ancestor's
        inheritedProperties = new CompositeValueMap(descendant.getProperties(), ancestor.getProperties());
    }

    public ValueMap getInheritedProperties()
    {
        return inheritedProperties;
    }
}

Now you can use this as follows

<sly data-sly-use.propHelper="com.sample.helpers.CustomInheritedPageProperties">>/sly>
<!--/* someProp here refers to the property you wish to get (inherited, of course)*/-->
<h1>propHelper.inheritedProperties.someProp</h1>

Upvotes: 2

Related Questions