Article summary

Summary

Discusses how to create a custom AEM column component. 

A special thank you to Praveen Dubey a member of the AEM community for contributing AEM code that is used in this article. 

Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
Java, Maven, HTML
Tested On Adobe Experience Manager 5.5, 5.6
 

Note:

You can download an AEM package that contains code and the OSGi bundle that are used in this article. Download the package and deploy using package manager. The purpose of this code is to show the community these concepts in action. That is, it's to illustrate how to write an AEM custom column component. This community code is for teaching purposes only and not meant to go into production as is.

You can view the application by using the following URL: http://localhost:4502/cf#/content/Column_Page.html (assuming you deploy on author). 

Download

Introduction

You can develop a custom Adobe Experience Manager (AEM) column control component to address your business requirements. An AEM column control component lets an AEM author split the content in the main panel of the web-page into multiple columns. Using a component dialog, an author defines the number of columns required and then create, delete, or move content within each of the columns. 

ColumnComponent

As specified, an author can change the number of columns and the border color by using the column's dialog.

dialog

Note:

If you deploy the package that is shown at the start of this artilce, you can skip these steps and read the article to understand the concepts. 

Create an Experience Manager application folder structure 

Create an Experience Manager application folder structure that contains templates, components, and pages by using CRXDE Lite. 

CQAppSetup

The following describes each application folder:

  • application name: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on. 
  • components: contains components that your application uses. 
  • page: contains page components. A page component is a script such as a JSP file.
    global: contains global components that your application uses.
  • template: contains templates on which you base page components. 
  • src: contains source code that comprises an OSGi component (this development article does not create an OSGi bundle using this folder). 
  • install: contains a compiled OSGi bundles container.

To create an application folder structure:

  1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.
  2. Select CRXDE Lite.
  3. Right-click the apps folder (or the parent folder), select Create, Create Folder.
  4. Enter the folder name into the Create Folder dialog box. Enter column_app
  5. Repeat steps 1-4 for each folder specified in the previous illustration. 
  6. Click the Save All button.

 

Note:

You have to click the Save All button when working in CRXDELite for the changes to be made.

Create a template 

You can create a template by using CRXDE Lite. A CQ template enables you to define a consistent style for the pages in your application. A template comprises of nodes that specify the page structure. For more information about templates, see Templates.

To create a template, perform these tasks:

1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.
2. Select CRXDE Lite.
3. Right-click the template folder (within your application), select Create, Create
Template.
4. Enter the following information into the Create Template dialog box:

  • Label: The name of the template to create. Enter templateColumnComponent
  • Title: The title that is assigned to the template.
  • Description: The description that is assigned to the template.
  • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter /apps/servlet_component/components/page/templateColumnComponent.
  • Ranking: The order (ascending) in which this template will appear in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.

5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.
6. Click Next for Allowed Parents.
7. Select OK on Allowed Children.
 

Create a render component that uses the template

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as a CQ developer to create scripts that perform specific functionality. For more information about components, see Components.

By default, a component has at least one default script, identical to the name of the component. To create a render component, perform these tasks:

1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/column_app/components/page, then select
Create, Create Component.

4. Enter the following information into the Create Component dialog box:

  • Label: The name of the component to create. Enter templateColumnComponent
  • Title: The title that is assigned to the component.
  • Description: The description that is assigned to the template.
  • Super Type:foundation/components/page. 

5. Select Next for Advanced Component Settings and Allowed Parents.

6. Select OK on Allowed Children.

7. Open the templateColumnComponent.jsp located at:/apps/column_app/components/page/templateColumnComponent/templateColumnComponent.jsp.

8. Enter the following JSP code.

<html>
<%@include file="/libs/foundation/global.jsp" %>
<cq:include script="/libs/wcm/core/components/init/init.jsp"/>
<body>
<h1>Here is where your custom AEM Column component will go</h1>
<cq:include path="par" resourceType="foundation/components/parsys" />
</body>
</html>

Create the AEM custom column component

After you setup the AEM folder structure, create the AEM custom column component. Perform these tasks using CRXDE Lite:

1. Right click on /apps/column_app/components and then select New, Component.

2. Enter the following information into the Create Component dialog box:

  • Label: The name of the component to create. Enter columncontrol.
  • Title: The title that is assigned to the component. Enter columncontrol.
  • Description: The description that is assigned to the template. Enter columncontrol.
  • Super Resource Type: Enter foundation/components/parbase.
  • Group: The group in the side rail or side kick where the component appears. Enter Adobe. (The developers component is located under the Adobe heading in the Touch UI side rail. Also appears in Adobe in the classic view sidekick.)
  • Allowed parents: Enter */*parsys.

3. Click Ok.

Add a dialog to the AEM component  

A dialog lets an author click on the component in the Touch UI (or Classic UI) view during design time and enter values that are used by the component. The component created in this development article lets the AEM author specify the number of columns in the column component and the border color. 

dialog2

The following illustration shows the JCR nodes that represent the dialog created in this section.

jcrDialog

To create the dialog, perform these tasks:

1.  Select /apps/column_app/components/columncontrol and select Create, Create Dialog.

2.  In the Title field, enter column.

3. Click Ok.

4.  Delete all nodes under /apps/column_app/components/columncontrol/dialog.

Create the Column tab

Create the only tab in the dialog named Column component. Perform these tasks.

1. Click on the following node: /apps/column_app/components/columncontrol/dialog.
2. Right click and select Create, Create Node
3. Enter the following values:
  • Name: items
  • Type: cq:Widget
4. Add the following property:
  • xtype (String) - tabpanel

5. Select the /apps/column_app/components/columncontrol/dialog/items node.

6. Right click and select Create, Create Node.

7. Enter the following values:

  • Name: items
  • Type: cq:WidgetCollection

8. Select the /apps/column_app/components/columncontrol/dialog/items/items node.

9. Right click and select Create, Create Node.
10. Enter the following values:
  • Name: colctrl
  • Type: cq:Widget
11. Add the following properties:
  • title (String) - Column control (title that appears on the tab)
  • xtype (String) - panel (defines the data type of this field.)
12. Click on the following node: /apps/column_app/components/columncontrol/dialog/items/items/colctrl.

13. Right click and select Create, Create Node.

14. Enter the following values:

  • Name: coltype
  • Type: cq:Widget

15. Select the Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items.

16. Right click and select Create, Create Node.
 
17. Enter the following values:
  • Name: coltype
  • Type: cq:Widget

18. Add the following properties:

  • allowBlank (Boolean) - false
  • editable (String) - true
  • fieldDescription (String) - select the type of column control to generate. Note: once columns are generated they cannot be re-generated.
  • fieldLabel (String) - Column type
  • name (String) - ./coltype
  • type (String) - select
  • xtype (String) - selection

19 . Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/coltype node.

20. Right click and select Create, Create Node.

21. Enter the following values:

  • Name: options
  • Type: cq:WidgetCollection

22. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/coltype/options node.

23. Right click and select Create, Create Node.

24. Enter the following values:

  • Name: col-8-4
  • Type: nt:unstructured

25. Add the following properties:

  • text (String) - 8-4 Column
  • value (String) - 8-4-col

26. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/coltype/options node.

27. Right click and select Create, Create Node.

28. Enter the following values:

  • Name: col-4-8
  • Type: nt:unstructured

29. Add the following properties:

  • text (String) - 4-8 Column
  • value (String) - 4-8-col
 

Note:

Repeat steps 26-29 for the following values: col-4-4-4, col-6-6, col-3-3-3-3, col-3-9, col-9-3, col-3-3-6, col-6-3-3, and col-3-6-3.

30. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/coltype node.

31. Right click and select Create, Create Node.

32. Enter the following values:

  • Name:listeners
  • Type: nt:unstructured
33. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items node.
34. Right click and select Create, Create Node.
35. Enter the following values:
  • Name:color
  • Type: cq:Widget

36. Add the following properties: 

  • defaultValue (String) - demo-border-blue
  • fieldLabel (String) - Border Color
  • name (String) - ./color
  • type (String) - select
  • xtype (String) - selection 
37. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/color node.
38. Right click and select Create, Create Node.
39. Enter the following values:
  • Name: options
  • Type: cq:WidgetCollection
40. Select the /apps/column_app/components/columncontrol/dialog/items/items/colctrl/items/color/options node.
41. Right click and select Create, Create Node.
42. Enter the following values:
  • Name: blue
  • Type: nt:unstructured
43. Add the following properties:
  • text (String) - Blue
  • value (String) - demo-border-blue
 

Note:

Repeats steps 40-43 for these color nodes: 

  • black node (text: Black, value: demo-border-black)
  • red node (text: Red, value: demo-border-red)
  • green node (text: Green, value: demo-border-green)

Add the Column CSS files to a cq:ClientLibraryFolder node

Add column control CSS files to an AEM client library node. The column control used in this example uses the bootstrap.min.css to define the columns layout in the AEM control. You can download the bootstrap.min.css from the following URL:

http://getbootstrap.com/getting-started/

clientlib

Add the bootstrap.min.css file to the ClientLibs folder:

  1. Right-click /apps/column_app/components then select New, Node.
  2. Make sure that the node type is cq:ClientLibraryFolder and name the node clientlibs.
  3. Right click on clientlibs and select Properties. Add the categories property to this node. Specify bootstrap and ensure the type is String[].
  4. Upload the bootstrap.min.css file to the clientlibs node using WebDev. 
  5. Add a TXT file to the clientlibs node named css.txt. Add bootstrap.min.css to this txt file.

columncontrol JSP

The columncontrol.jsp is the main JSP file for the component and is located at: 

/apps/column_app/components/columncontrol/columncontrol.jsp

This application logic located in the columncontrol.jsp defines the columns based on the selection that an author selected in the dialog. For each option in the dialog, there is a corresponding code section that defines the column layout. When creating a column component, it's very important to ensure that there is application logic to map to a selection in the dialog. 

These lines of code correspond to the selection for 8-4-col that appears in the dialog.

<c:when test="${coltype eq '8-4-col'}">
<div class="col-sm-8 ${color}" ><cq:include path="col-8-4-1" resourceType="/libs/foundation/components/parsys" /></div>
<div class="col-sm-4 ${color}"><cq:include path="col-8-4-2" resourceType="/libs/foundation/components/parsys" /></div>
</c:when>

Also, notice that the resourcetype is  /libs/foundation/components/parsys. This defines the resource type.  

The following code represents the entire columncontrol.jsp file.

<jsp:directive.include file="/libs/foundation/global.jsp"/>
<cq:includeClientLib categories="bootstrap" />
<jsp:directive.page session="false" />

<jsp:scriptlet>
	pageContext.setAttribute("coltype", xssAPI.filterHTML(properties.get("coltype","")));
</jsp:scriptlet>

<c:if test="${empty coltype}">
	This is column control component
</c:if>

<c:if test="${not empty coltype}">
<style>
		.demo-border-blue{
    border:1px solid #0066FF;
} 
        .demo-border-black{
    border:1px solid #000000;
} 
        .demo-border-green{
    border:1px solid #19D1A3;
} 
        .demo-border-red{
    border:1px solid #FF4D4D;
} 
    </style>
<c:set var = "column" value = "${properties.coltype}" />
<c:set var = "color" value = "${properties.color}" />
<div class="row">
	<c:choose>
		<c:when test="${coltype eq '8-4-col'}">
		  	<div class="col-sm-8 ${color}" ><cq:include path="col-8-4-1" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-4 ${color}"><cq:include path="col-8-4-2" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '4-8-col'}">
	  		<div class="col-sm-4 ${color}"><cq:include path="col-4-8-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-8 ${color}"><cq:include path="col-4-8-2" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '4-4-4-col'}">
		  	<div class="col-sm-4 ${color}"><cq:include path="col-4-4-4-1" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-4 ${color}"><cq:include path="col-4-4-4-2" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-4 ${color}"><cq:include path="col-4-4-4-3" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '6-6-col'}">
		  	<div class="col-sm-6 ${color}"><cq:include path="col-6-6-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-6 ${color}"><cq:include path="col-6-6-2" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '3-3-3-3-col'}">
		  	<div class="col-sm-3  ${color}"><cq:include path="col-3-3-3-3-1" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-3  ${color}"><cq:include path="col-3-3-3-3-2" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-3  ${color}"><cq:include path="col-3-3-3-3-3" resourceType="/libs/foundation/components/parsys" /></div>
		 	<div class="col-sm-3  ${color}"><cq:include path="col-3-3-3-3-4" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '2-2-2-2-2-2-col'}">
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-1" resourceType="/libs/foundation/components/parsys" /></div>
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-2" resourceType="/libs/foundation/components/parsys" /></div>
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-3" resourceType="/libs/foundation/components/parsys" /></div>
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-4" resourceType="/libs/foundation/components/parsys" /></div>
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-5" resourceType="/libs/foundation/components/parsys" /></div>
			<div class="col-xs-6 col-sm-4 col-md-2 ${color}"><cq:include path="col-2-2-2-2-2-2-6" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '3-9-col'}">
			<div class="col-sm-3  ${color}"><cq:include path="col-3-9-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-9  ${color}"><cq:include path="col-3-9-2" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '9-3-col'}">
			<div class="col-sm-9  ${color}"><cq:include path="col-9-3-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-3  ${color}"><cq:include path="col-9-3-2" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '3-3-6-col'}">
			<div class=" col-sm-3 ${color}"><cq:include path="col-3-3-6-1" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class=" col-sm-3 ${color}"><cq:include path="col-3-3-6-2" resourceType="/libs/foundation/components/parsys" /></div>
		  	<div class="col-sm-6 ${color}"><cq:include path="col-3-3-6-3" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '6-3-3-col'}">
			<div class="col-sm-6  ${color}"><cq:include path="col-6-3-3-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-3  ${color}"><cq:include path="col-6-3-3-2" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-3  ${color}"><cq:include path="col-6-3-3-3" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
		<c:when test="${coltype eq '3-6-3-col'}">
			<div class="col-sm-3 ${color}"><cq:include path="col-3-6-3-1" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-6 ${color}"><cq:include path="col-3-6-3-2" resourceType="/libs/foundation/components/parsys" /></div>
	  		<div class="col-sm-3 ${color}"><cq:include path="col-3-6-3-3" resourceType="/libs/foundation/components/parsys" /></div>
		</c:when>
	</c:choose>
</div>
</c:if>

Create the EditConfig node

cq:EditConfig node defines the behaviour of the component. See Configuring with cq:EditConfig Properties.

Perform the following tasks:

1. Select /apps/column_app/components/columncontrol.

2. Right click and select Create, Create Node

3. Enter the following values:

  • Name: cq:editConfig
  • Type: cq:EditConfig

4. Add the following property:

  • cq:dialogMode (String) - floating
5. Select /apps/column_app/components/columncontrol/cq:editConfig.
6. Right click and select Create, Create Node.
7. Enter the following values:
  • Name: cq:listeners
  • Type: cq:EditListenersConfig
8. Add the following property:
  • afteredit (String) - REFRESH_PAGE
afteredit
afteredit

Create a CQ web page that uses the movie-launch component

The final task is to create an AEM page that uses the column component, that is shown in the followng illustration. 

 

clientpage

Create an AEM page that displays the component.

  1. Go to the CQ Websites page at http://localhost:4502/siteadmin#/content.
  2. Select New Page.
  3. Specify the title of the page in the Title field. Enter Column_Page.
  4. Specify the name of the page in the Name field.
  5. Select templateColumnComponent from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information, the template will not show up in the New Page dialog box.
  6. Open the page by clicking the Column_Page page.
  7. The columncontrol component will be under the Adobe heading in the sidekick. Drag this component onto the AEM page. 
  8. Open the columncontrol component dialog and enter values into the dialog fields.

Populate the AEM side kick

If the CQ sidekick is empty, you can populate it by clicking the Design button located at the bottom of the sidekick. Next click the Edit button that appears and select Adobe from the list of categories. To view the sidekick with the Adobe category, click the down arrow icon that appears on the sidekick. Drag the columncontrol component on the AEM web page. Double click on the component and you see the dialog that you created in this development article.  

The following illustration, shows the Adobe category where the component is located. 

adobe

See also

Congratulations, you have just created an AEM custom column component that you can use in your projects. Please refer to the AEM community page for other articles that discuss how to build AEM services/applications.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy