Adobe Experience Manager Blog

AEM concepts, snippets and implementation

Category Archives: Uncategorized

AEM Template Editor – Design configuration via policies

0

In template editors, policies are used to configure component design. Example: component’s design configurations,  allowed components for a container, mapping asset into components etc.

Configuring a template-editor’s policy is similar to a Static template’s design dialog. Following are the steps to define and access a new policy:

Step 1: Create policy configuration dialog

A component’s policy dialog is defined by adding a cq:design_dialog to the component. Example:

Capture1.PNG

Sample .content.xml for design dialog:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
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"
jcr:title="My Title Component"
sling:resourceType="cq/gui/components/authoring/dialog">
    <content jcr:primaryType="nt:unstructured"
       sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <tabs jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs"
                maximized="{Boolean}true">
                <items jcr:primaryType="nt:unstructured">
                    <properties
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Available Stage types"
                        sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                        margin="{Boolean}true">
                        <items jcr:primaryType="nt:unstructured">
                            <content
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                margin="{Boolean}false">
                                <items jcr:primaryType="nt:unstructured">
                                    <title
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                        fieldLabel="Title"
                                        name="./title"/>
                                </items>
                            </content>
                        </items>
                   </properties>
               </items>
            </tabs>
        </items>
    </content>
</jcr:root>

Step 2: Configuring policy

Once the design dialog is created:

  • Open the template in Structure mode.
  • Click on the component
  • Following button should now be available to configure the design properties.

Sprints.PNG

Policy Storage and sharing:

  • Policies are stored in following location by default:

/conf/project_name/settings/wcm/policies/component_name/policy_randomNumber

Policies can be also be stored in /apps or /libs folder. In this case the resource will be resolved in following preference order: /conf, /apps, /libs.

  • Please observe in the policy path, that policies are stored centrally for a project. This enables authors to share a design policy among multiple templates.
  • Template -> policy mapping is done by referring policy via:

cq:policy=/conf/project_name/settings/wcm/policies/component_name/policy_randomNumber

Capture.PNG

       At location:

    /conf/project_name/settings/wcm/templates/template-name/policies/jcr:content/root/component_name

Step 3: Accessing policy

A component’s policy configuration can be accessed by ContentPolicyManager. Sharing an example below:

import javax.annotation.PostConstruct;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import com.day.cq.wcm.api.policies.ContentPolicy;
import com.day.cq.wcm.api.policies.ContentPolicyManager;

@Model(adaptables = Resource.class)
public class StageModel {
    @SlingObject
    private ResourceResolver resourceResolver;

    /** The resource. */
    @Self
    protected Resource resource;

    private String title;

    @PostConstruct
    protected void constructStageType(){
        ContentPolicyManager policyManager = resourceResolver.adaptTo(ContentPolicyManager.class);
        if (policyManager != null) {
            ContentPolicy contentPolicy = policyManager.getPolicy(resource);
            if (contentPolicy != null) {
                title= (String) contentPolicy.getProperties().get("title");
            }
        }
    }

    /**
    * @return title
    */
    public String getTitle() {
        return title;
    }
}
Advertisements

AEM – Coral 2 multifield with acs-aem-commons JSON_STORE

0

In AEM component dialog, we often implement multifield which comprise of multiple widgets. Here we would cover  multifield which would store values in json format using:

STEP 1: Create a component.

STEP 2: Create component dialog with multifield comprising of:

  • textfield
  • pathbrowser

Add acs-commons-nested=”JSON_STORE” to the multifield

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" 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"       jcr:title="Navigation"       sling:resourceType="cq/gui/components/authoring/dialog">
     <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">
         <items jcr:primaryType="nt:unstructured">
             <tabs jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">
                <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/tabs" type="nav"/>
                    <items jcr:primaryType="nt:unstructured">
                        <navigationitems jcr:primaryType="nt:unstructured" jcr:title="Navigation Items" sling:resourceType="granite/ui/components/foundation/section">
                            <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns" margin="{Boolean}false"/>
                                <items jcr:primaryType="nt:unstructured">
                                    <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">
                                        <items jcr:primaryType="nt:unstructured">
                                            <navigationitems jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/multifield" class="full-width" fieldDescription="Click 'Add field' to add a new item" fieldLabel="Navigation Items">
                                                <field jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/fieldset" acs-commons-nested="JSON_STORE" name="./navigationItems">
                                                    <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns" method="absolute"/>
                                                        <items jcr:primaryType="nt:unstructured">
                                                           <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">
                                                               <items jcr:primaryType="nt:unstructured">
                                                                   <label jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" fieldLabel="Label" name="./linktext"/>
                                                                   			<link jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/pathbrowser" fieldLabel="Link" name="./linkURL" rootPath="/content"/>
                                                                </items>
                                                            </column>
                                                       </items>
                                            </field>
                                      </navigationitems>
                                 </items>
                             </column>
                         </items>
                     </navigationitems>
                 </items>
             </tabs>
         </items>
     </content>
</jcr:root>

STEP 3: Add dependencies to the pom.xml

Incase, the AEM doesn’t export javax.json.JsonObject API, then you would have to import the bundles in AEM.

<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-json_1.0_spec</artifactId>
    <version>1.0-alpha-1</version>
</dependency>
<dependency>
    <groupId>org.apache.johnzon</groupId>
    <artifactId>johnzon-core</artifactId>
    <version>1.0.0</version>
</dependency>

STEP 4: Create Sling Model to access multifield values. The values returned as a List would be iterated in Component’s sightly to display links.

Bean to hold a link’s details:

/** * NavigationItem for Links. */
public class NavigationItem {
    private String linktext;
    private String linkURL;
    public NavigationItem(String linktext, String linkURL){
        this.linktext = linktext;
        this.linkURL = linkURL;
    }
    public String getLinktext() {
        return linktext;
    }
    public void setLinktext(String linktext) {
        this.linktext = linktext;
    }
    public String getLinkURL() {
        return linkURL;
    }
    public void setLinkURL(String linkURL) {
        this.linkURL = linkURL;
    }
}

Sling Model to gather details of all configured links:

package blog.techrevel.core.models;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;

import blog.techrevel.NavigationItem;

/** * A model bean for the link component */
@Model(adaptables = Resource.class)
public class ProductNavigationModel {

   private static final String LINK_URL = "linkURL";
   private static final String LINK_TEXT = "linktext";

   @Inject
   @Optional
   private String[] navigationItems;
   private List<NavigationItem> list;

   @PostConstruct protected void init() {
       if (navigationItems != null) {
           this.list = new ArrayList<>();
           for (String linkJsonString : navigationItems) {
              try (StringReader stringReader = new StringReader(linkJsonString);
                  JsonReader jsonReader = Json.createReader(stringReader)) {
                  JsonObject linkJsonObject = jsonReader.readObject();
                  String linkPath = linkJsonObject.getString(LINK_URL);
                   list.add(new NavigationItem(linkJsonObject.getString(LINK_TEXT), linkPath));
              }
          }
       }
    }
    public List<NavigationItem> getList() {
        return list;
    }
}

STEP 5: Render links in Component’s sightly by accessing the Sling Model

<div data-sly-use.linkModel="blog.techrevel.core.models.ProductNavigationModel">
        <!--/*Links*/-->
        <sly data-sly-repeat.item="${linkModel.list}">
            <a href="${item.linkURL}"> ${item.linktext}</a>
        </sly>
        <sly data-sly-test="${!linkModel.list}">Navigation Component</sly></div>

Verified on AEM 6.3 with acs-aem-commons package version 3.9.0