AEM 61 - Touch UI Multiple Root Paths in Tags Picker

Goal


Support multiple root paths in Tags Picker of Touch UI. For Classic UI check this post

This is a picker extension only, searching inline still returns every tag available

For a similar Path Browser Picker extension check this post

Demo |  Package Install


Tags Picker (Product)



Tags Picker with Multiple Root Paths Configuration (Extension)





Tags Picker with Multiple Root Paths (Extension) eaemTagsRootPaths -  /etc/tags/geometrixx-outdoors/activity, /etc/tags/geometrixx-media/entertainment




Solution


1) Login to CRXDE Lite http://localhost:4502/crx/de, create folder /apps/touchui-tags-picker-custom-root-paths

2) Create folder /apps/touchui-tags-picker-custom-root-paths/tags-picker and file /apps/touchui-tags-picker-custom-root-paths/tags-picker/tags-picker.jsp, add the following code. This picker jsp extends ootb tags picker jsp /libs/cq/gui/components/common/tagspicker to set the data source url /apps/touchui-tags-picker-custom-root-paths/content/tag-column-wrapper.html (ootb its /libs/wcm/core/content/common/tagbrowser/tagbrowsercolumn.html set in /libs/cq/gui/components/common/tagspicker/render.jsp). Had the pickerSrc attribute been available as configuration param like rootPath, this step would have not been required...

<%@ page import="com.adobe.granite.ui.components.Config" %>
<%@ page import="org.apache.commons.lang3.StringUtils" %>
<%@ page import="org.apache.commons.lang3.ArrayUtils" %>
<%@include file="/libs/granite/ui/global.jsp" %>

<sling:include resourceType="/libs/cq/gui/components/common/tagspicker" />

<%
    Config cfg = cmp.getConfig();
    String[] eaemTagsPaths = cfg.get("eaemTagsRootPaths", String[].class);

    //tags paths not set, continue with ootb functionality
    if(ArrayUtils.isEmpty(eaemTagsPaths)){
        return;
    }
%>

<script type="text/javascript">
    (function(){
        var EAEM_TAGS_PATHS = "eaemtagsrootpaths",
            BROWSER_COLUMN_PATH = "/apps/touchui-tags-picker-custom-root-paths/content/tag-column-wrapper.html";

        function changeTagsPickerSrc(){
            var $eaemTagsPicker = $("[data-" + EAEM_TAGS_PATHS + "]");

            if($eaemTagsPicker.length == 0){
                return;
            }

            var browserCP = BROWSER_COLUMN_PATH + '<%=StringUtils.join(eaemTagsPaths, ",")%>';

            $eaemTagsPicker.attr("data-picker-src", browserCP);
        }

        changeTagsPickerSrc();
    }());
</script>

3) Create sling:Ordered folder /apps/touchui-tags-picker-custom-root-paths/content and nt:unstructured node /apps/touchui-tags-picker-custom-root-paths/content/tag-column-wrapper with sling:resourceType /apps/touchui-tags-picker-custom-root-paths/tag-browser-column

4) To add the picker browser column renderer extension, create folder /apps/touchui-tags-picker-custom-root-paths/tag-browser-column and file /apps/touchui-tags-picker-custom-root-paths/tag-browser-column/tag-browser-column.jsp with the following code. It includes /libs/wcm/core/content/common/tagbrowser/tagbrowsercolumn.html for getting the columns html and later removes unwanted root nodes

<%@ page import="org.apache.sling.api.request.RequestPathInfo" %>
<%@ page import="org.apache.sling.commons.json.JSONArray" %>
<%@include file="/libs/granite/ui/global.jsp" %>

<%!
    String TAG_BROWSER_COLUMN_PATH = "/libs/wcm/core/content/common/tagbrowser/tagbrowsercolumn.html";
    String TAG_NAV_MARKER = "eaemTagNavMarker";

    private String getParentTagPath(String tagPath) {
        return tagPath.substring(0, tagPath.lastIndexOf("/"));
    }

    private JSONArray getTagPathsJson(String[] tagPaths){
        JSONArray array = new JSONArray();

        for(String tagPath: tagPaths){
            array.put(tagPath);
        }

        return array;
    }
%>

<%
    RequestPathInfo pathInfo = slingRequest.getRequestPathInfo();
    String tagPaths[] = pathInfo.getSuffix().split(",");

    for(String tagPath: tagPaths){
        String includePath = TAG_BROWSER_COLUMN_PATH + getParentTagPath(tagPath);

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

<script type="text/javascript">
    (function(){
        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 addRootTags(){
            var $tagMarker = $("#<%=TAG_NAV_MARKER%>"),
                $navs = $tagMarker.prevAll("nav"),
                tagPaths = <%=getTagPathsJson(tagPaths)%>,
                rootTags = [];

            //find the root tags
            $.each(tagPaths, function(index, tagPath){
                rootTags.push($navs.find("[data-value='" + tagPath + "']"));
            });

            removeAddnNavsGetColumn($navs).append(rootTags);

            //remove the tag marker div
            $tagMarker.remove();
        }

        addRootTags();
    }());
</script>

5) In the component dialog add necessary configuration eaemTagsRootPaths and sling:resourceType /apps/touchui-tags-picker-custom-root-paths/tags-picker. For example, here is a sample configuration added on ootb page properties /libs/foundation/components/page/cq:dialog/content/items/tabs/items/basic/items/column/items/title/items/tags. This is for demonstration only, never touch /libs





7 comments:

  1. Thanks ! this was informative ! Can you suggest about how can we restrict same from inline search

    ReplyDelete
  2. Hi, This is working fine but one namespace is getting displayed twice. In jsp $navs.find("[data-value='/etc/tags']"), this is returning the size as 2.

    ReplyDelete
    Replies
    1. I can see the same issue, any fix for this?

      Delete
  3. Hi, how can this be modified to get the internationalized tag values for the selected language?

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Try to make such changes in tag-browser-column.jsp. Most likely, changes are needed elsewhere, but it works for me.
    <%
    RequestPathInfo pathInfo = slingRequest.getRequestPathInfo();
    String tagPaths[] = pathInfo.getSuffix().split(",");
    String includePath = TAG_BROWSER_COLUMN_PATH + getParentTagPath(tagPaths[0]);
    %>

    ReplyDelete
  6. In tag-browser-column.jsp
    by replacing the line
    rootTags.push($navs.find("[data-value='" + tagPath + "']"));
    with
    rootTags.push($navs.find("[data-value='" + tagPath + "']")[index]);
    resolved duplicate issue.

    ReplyDelete