Search code examples
aemxtype

How to filter tags in a component dialog. Adobe CQ


I am trying to filter the tags in a component dialog. I know that I can filter it by namespace, however that applies only to root level. Can I filter the tag selection one level deeper?

for example:

  • etc
    • tags
      • namespace
        • article-type
          • blog
          • news
        • asset-type
          • image
          • video

I want to filter the tags in the component dialog so the user can only select the tags under 'article-type'.

Thanks,


Solution

  • Yes and no. Officially you can go deeper according to the widget API, but there is a "bug" in the Widget JavaScript file that prevents it to work. I had the same issue and I just overwrite this JavaScript file.

    Widget definition:

    <article jcr:primaryType="cq:Widget"
        fieldLabel="Article Type"
        name="./cq:tags"
        tagsBasePath="/etc/tags/namespace"
        xtype="tags">
        <namespaces jcr:primaryType="cq:WidgetCollection">
            <ns1 jcr:primaryType="nt:unstructured" maximum="1" name="article-type" />  
        </namespaces>  
    </article>
    <asset jcr:primaryType="cq:Widget"
        fieldLabel="Asset Type"
        name="./cq:tags"
        namespaces="[asset-type]"
        tagsBasePath="/etc/tags/offering"
        xtype="tags"/>
    

    In this case only one Tag below article-type can be selected; you can limit the number with the maximum attribute. The asset-type has no limits. So choose the option that suits your need.

    JavaScript overwrite:

    To make this work, you need to change the method CQ.tagging.parseTag in /libs/cq/tagging/widgets/source/CQ.tagging.js:

    // private - splits tagID into namespace and local (also works for title paths)
    CQ.tagging.parseTag = function(tag, isPath) {
        var tagInfo = {
            namespace: null,
            local: tag,
            getTagID: function() {
                return this.namespace + ":" + this.local;
            }
        };
    
        var tagParts = tag.split(':');
        if (tagParts[0] == 'article-type' || tagParts[0] == 'asset-type') {
            var realTag = tagParts[1];
            var pos = realTag.indexOf('/');
            tagInfo.namespace = realTag.substring(0, pos).trim();
            tagInfo.local = realTag.substring(pos + 1).trim();
        }
        else {
            // parse tag pattern: namespace:local
            var colonPos = tag.indexOf(isPath ? '/' : ':');
            if (colonPos > 0) {
                // the first colon ":" delimits a namespace
                // don't forget to trim the strings (in case of title paths)
                tagInfo.namespace = tag.substring(0, colonPos).trim();
                tagInfo.local = tag.substring(colonPos + 1).trim();
            }
        }
        return tagInfo;
    };