AEM 61 - Touch UI Multiple Root Paths in Path Browser Picker


Support multiple root paths in Path Browser Picker of Touch UI. Path browser /libs/granite/ui/components/foundation/form/pathbrowser, widget configuration supports one root path ootb (can be configured by setting rootPath as shown in demo). This extension is for making the picker support multiple root paths...

Check this post for a similar Tags Picker extension

Demo | Package Install (/apps/touch-ui-pathbrowser-multiple-rootpaths,/apps/experience-aem/sample-component)


A sample path browser widget configuration with pickerSrc property set to /apps/touch-ui-pathbrowser-multiple-rootpaths/content/column.html?predicate=hierarchy&eaemRootPaths=/content/dam/geometrixx-outdoors/banners,/content/dam/geometrixx-gov,/content/dam/geometrixx-unlimited/covers


With pickerSrc having parameter eaemRootPaths set to comma separated values


the picker shown would be...


1) Create nt:folder /apps/touch-ui-pathbrowser-multiple-rootpaths, sling:Ordered folder /apps/touch-ui-pathbrowser-multiple-rootpaths/content and nt:unstructured node /apps/touch-ui-pathbrowser-multiple-rootpaths/content/column with sling:resourceType /apps/touch-ui-pathbrowser-multiple-rootpaths/column

2) To render the above content/column node, create nt:folder /apps/touch-ui-pathbrowser-multiple-rootpaths/column and nt:file /apps/touch-ui-pathbrowser-multiple-rootpaths/column/column.jsp, add the following code

<%@ page import="" %>
<%@ page import="org.apache.commons.lang3.StringUtils" %>
<%@ page import="org.apache.jackrabbit.util.Text" %>
<%@include file="/libs/granite/ui/global.jsp" %>

    String COLUMN_PATH = "/libs/wcm/core/content/common/pathbrowser/column.html";
    String NAV_MARKER = "eaemNavMarker";

    private String getParentPath(String path) {
        return path.substring(0, path.lastIndexOf("/"));

    private JSONArray getPathsJson(String[] paths){
        JSONArray array = new JSONArray();

        for(String path: paths){

        return array;

    String rootPathsStr = slingRequest.getParameter("eaemRootPaths");
    String[] rootPaths = StringUtils.isEmpty(rootPathsStr) ? new String[0] : rootPathsStr.split(",");

    for(String path: rootPaths){
        String includePath = COLUMN_PATH + Text.escapePath(getParentPath(path));

        <sling:include path="<%=includePath%>"  />
<div id="<%=NAV_MARKER%>">

<script type="text/javascript">
        function removeAddnNavsGetColumn($navs){
            $navs.not(":first").remove(); //remove all additional navs
            return $navs.first().children(".coral-ColumnView-column-content").html("");//get the column of first nav

        function addRoots(){
            var $marker = $("#<%=NAV_MARKER%>"),
                $navs = $marker.prevAll("nav"),
                paths = <%=getPathsJson(rootPaths)%>,
                rootPaths = [];

            //find the root paths
            $.each(paths, function(index, path){
                rootPaths.push($navs.find("[data-value='" + path + "']"));


            //remove the marker div


3) The picker column renderer created above includes the ootb column renderer /libs/wcm/core/content/common/pathbrowser/column.html for parents of each root path (#33), does some simple dom manipulation on the client side to remove unwanted node html

1 comment:

  1. i got some bug ,when i am using different content path it get duplicate and when i save the value of path it's not populate in the dialog.