April 27, 2020
Estimated Post Reading Time ~

How to customize the page properties Dialog to include dynamic DropDownList

This post will explain the details to customize page properties Dialog in both Touch and Classic UI's, the version used for implementing this is Adobe Experience Manager(AEM) 6.1.

The basic page properties dialog will be displayed if the sling:resourceSuperType of the page rendering component is specified as foundation page component(wcm/foundation/components/page for Sightly and foundation/components/page for JSP)

Steps to customize the basic page properties and including dynamic DropDownList to the dialog.

/apps/training/components/page-content/ will be referred to as the page rendering component path in the post.

Classic UI:Copy /libs/foundation/components/page/dialog to /apps/training/components/page-content/
Rename the new node to required name e.g. custom

Copy /libs/foundation/components/page/tab_basic to /apps/training/components/page-content/
Rename /apps/training/components/page-content/tab_basic to required name e.g tab_custom

Remove all the nodes under /apps/training/components/page-content/tab_custom/items

Change path value in the node /apps/training/components/page-content/dialog/items/tabs/items/custom to /apps/training/components/page-content/tab_custom.infinity.json

Change title property of the node /apps/training/components/page-content/tab_custom to required value e.g Custom

Save All configurations

Open the page from site Admin(e.g. http://localhost:4502/cf#/content/training-site/en.html), now the new tab(Custom) will be added to the page properties with empty panel



Adding a textfield to the custom panel:Create a new node of type cq:Widget under /apps/training/components/page-content/tab_custom/items

NameTypeValue
xtype String textfield
name String ./fieldName e.g. ./customtext
fieldLabel String Enter the field lable

Save All configurations - open the page(e.g. http://localhost:4502/cf#/content/training-site/en.html), the new textfield will be displayed under Custom tab.




Adding a dynamic DropDownList:
Create a servlet that returns the JSON data.

import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONObject;
import org.apache.felix.scr.annotations.Properties;

@Service(value = Servlet.class)
@Component(immediate = true, metatype = true)
@Properties({
@Property(name = "sling.servlet.paths", value = "/services/getCountries"),
@Property(name = "service.description", value = "returns list of countries"),
@Property(name = "label", value = "GetCountryList") })
public class GetCountryList extends SlingSafeMethodsServlet{

private static final long serialVersionUID = 1180258251365536303L;

@Override
protected void doGet(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException {
try{
response.setContentType("application/json; charset=utf-8");
response.setCharacterEncoding("UTF-8");

JSONArray contryJsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("text", "US").put("value", "United States");
contryJsonArray.put(jsonObject);
jsonObject = new JSONObject();
jsonObject.put("text", "UK").put("value", "United Kingdom");
contryJsonArray.put(jsonObject);
response.getWriter().write(contryJsonArray.toString());
}catch(Exception e){
}

}
}

Create a new node of type cq:Widget under /apps/training/components/page-content/tab_custom/items

Add the following properties to the new node

NameTypeValue
xtype String selection
name String ./fieldName e.g. ./customtext
fieldLabel String Enter the field label
type String select
options String Servlet path that returns JSON data (e.g. /services/getCountries)

Save All Configurations - open the page(e.g. http://localhost:4502/cf#/content/training-site/en.html), the new DropDownList will be displayed under Custom tab.



Touch UI:
Copy /libs/foundation/components/page/cq:dialog to /apps/training/components/page-content

Copy /apps/training/components/page-content/cq:dialog/content/items/tabs/items/basic and paste to /apps/training/components/page-content/cq:dialog/content/items/tabs/items

Rename the node name to required value e.g Custom

Change the jcr:title property of the node e.g Custom

Remove nodes that are not required and create/rename nodes as required(better remove all the nodes under /apps/training/components/page-content/cq:dialog/content/items/tabs/items/custom/items/column/items and create the required nodes).

Adding a Dynamic Dropdownlist:
Create a servlet that will return the DataSource

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import com.adobe.granite.ui.components.ds.DataSource;
import com.adobe.granite.ui.components.ds.SimpleDataSource;
import com.adobe.granite.ui.components.ds.ValueMapResource;
@SlingServlet(resourceTypes = "/services/getCountryList")
public class GetCountryListServlet extends SlingSafeMethodsServlet{
private static final long serialVersionUID = 1180258251365536303L;

@Override
protected void doGet(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException {
try{
ResourceResolver resolver = request.getResourceResolver();
List<Resource> countryList = new ArrayList<Resource>();
ValueMap valueMap = new ValueMapDecorator(new HashMap<String, Object>());
valueMap.put("value","United States");
valueMap.put("text","US");
countryList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", valueMap));

valueMap = new ValueMapDecorator(new HashMap<String, Object>());
valueMap.put("value","United Kingdom");
valueMap.put("text","UK");
countryList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", valueMap));

DataSource dataSource = new SimpleDataSource(countryList.iterator());
request.setAttribute(DataSource.class.getName(), dataSource);
}catch(Exception e){
e.printStackTrace();
}
}

}

The servlet is not registered with the above code in AEM 6.4, @Component is expected for the servlet.

Servelet - AEM 6.4

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.*;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import com.adobe.granite.ui.components.ds.DataSource;
import com.adobe.granite.ui.components.ds.SimpleDataSource;
import com.adobe.granite.ui.components.ds.ValueMapResource;
import org.osgi.service.component.annotations.Component;
import org.osgi.framework.Constants;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(service=Servlet.class,
property={

Constants.SERVICE_DESCRIPTION + "=Get Country List Servlet",
"sling.servlet.methods=" + "GET",
"sling.servlet.resourceTypes="+ "/services/getCountryList"
})

public class GetCountryListServlet extends SlingSafeMethodsServlet{
private static final long serialVersionUID = 1180258251365536303L;
Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
protected void doGet(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException {
try{
logger.error("inside...");
ResourceResolver resolver = request.getResourceResolver();
List<Resource> countryList = new ArrayList<Resource>();
ValueMap valueMap = new ValueMapDecorator(new HashMap<String, Object>());
valueMap.put("value","United States");
valueMap.put("text","US");
countryList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", valueMap));

valueMap = new ValueMapDecorator(new HashMap<String, Object>());
valueMap.put("value","United Kingdom");
valueMap.put("text","UK");
countryList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", valueMap));

DataSource dataSource = new SimpleDataSource(countryList.iterator());
logger.error("dataSource...");
request.setAttribute(DataSource.class.getName(), dataSource);
}catch(Exception e){
logger.error("error..."+e.getMessage());
e.printStackTrace();
}
}

}

Create a node(e.g. customlist) with type nt:unstructured under /apps/training/components/page-content/cq:dialog/content/items/tabs/items/custom/items/column/items

Add the following properties to the new node
NameTypeValue
emptyTextStringselection
nameString./fieldName e.g. ./customlist
fieldLabelStringEnter the field label
sling:resourceTypeStringgranite/ui/components/foundation/form/select

Create a node with name datasource and type nt:unstructured under the node created in the previous step
Enter the below property
NameTypeValue
sling:resourceTypeStringServlet Path(e.g. /services/getCountryList)

Save All Configurations - open the page(e.g. http://localhost:4502/editor.html/content/training-site/en.html), the new fileds/DropDownList will be displayed under the Custom tab.


By aem4beginner

No comments:

Post a Comment

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