Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.

Using "Select Panel" on a custom component

Avatar

Level 2

Hi All,

I am doing a deep dive on how the "Select Panel" tool works. I can't find much information about it and am stuck.

I've been examining the WCM Core Components Tabs/Carousel/Accordion that use "Select Panel". These use a "childeditor" resourceType, which means that authors pick components in the dialog. I want to create a component that has sections with an optional hidden layout container. "Select Panel" is then used to select which is active similar to how the Carousel or Tab bring a specific panel into view.

For this experiment, I created a coral3 multifield dialog with a Title, Text, and Container checkbox. If checked, a container is inserted (resourceType='wcm/foundation/components/responsivegrid').

I was able to register the component to panelcontainer, but I can't get it to do anything. This is where I am stuck:

1) How can I pass the Title field as the Component name instead of it's defaulting to "Layout Container"?

2) It doesn't move, select, or re-order. It acts like it might, but it does nothing. Is there an event listener registration step I missed? I tried moving and nothing reorders. I tried selecting and do not see any classes changing when looking at Inspect Elements.

3) Can "Move" be disabled?

SelectPanel.jpg

HTL

<sly data-sly-use.props="com.pnc.core.models.DemoPanelSelector">

    <div data-sly-list.demo="${props.demoItems.listChildren}"

            class="cmp-demoPanelSelector"

            data-cmp-is="demoPanelSelector">

        <h2>${demo.title}</h2>

        <p>${demo.text}</p>

        <sly data-sly-test="${demo.hasContainer}" data-cmp-hook-demopanelselector="item">

            <div class="cmp-demoPanelSelector__item" data-sly-resource="${ demo.mfRef @ resourceType='wcm/foundation/components/responsivegrid'}"></div>

        </sly>

    </div>

</sly>

cq:EditConfig

<?xml version="1.0" encoding="UTF-8"?>

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"

    jcr:primaryType="cq:EditConfig">

    <cq:listeners

        jcr:primaryType="cq:EditListenersConfig"

        afterchilddelete="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_DELETE"

        afterchildinsert="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_INSERT"

        afterchildmove="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_MOVE"/>

</jcr:root>

editorhook.js

(function(channel) {

    "use strict";

    channel.on("cq-editor-loaded", function(event) {

        if (window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.panelcontainer &&

            window.CQ.CoreComponents.panelcontainer.v1 && window.CQ.CoreComponents.panelcontainer.v1.registry) {

            window.CQ.CoreComponents.panelcontainer.v1.registry.register({

                name: "cmp-demoPanelSelector",

                selector: ".cmp-demoPanelSelector",

                itemSelector: "[data-cmp-hook-demopanelselector='item']",

                itemActiveSelector: ".cmp-demoPanelSelector__item--active"

            });

        }

    });

})(jQuery(document));

cq:Dialog

<?xml version="1.0" encoding="UTF-8"?> 

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"

  xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0

  xmlns:granite="http://www.adobe.com/jcr/granite/1.0"

    jcr:primaryType="nt:unstructured" 

    jcr:title="Basic Demo Panel Container Test" 

    sling:resourceType="cq/gui/components/authoring/dialog"

    extraClientlibs="[core.pnc.components.demoPanelSelector.v1.editor]"> 

    <content 

        jcr:primaryType="nt:unstructured" 

        sling:resourceType="granite/ui/components/coral/foundation/container"> 

        <items jcr:primaryType="nt:unstructured"> 

            <tabs 

                jcr:primaryType="nt:unstructured" 

                sling:resourceType="granite/ui/components/coral/foundation/tabs" 

                maximized="{Boolean}true"> 

                <items jcr:primaryType="nt:unstructured"> 

                    <Basic 

                        jcr:primaryType="nt:unstructured" 

                        jcr:title="Basic" 

                        sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns" 

                        margin="{Boolean}false"> 

                        <items jcr:primaryType="nt:unstructured"> 

                            <column 

                                jcr:primaryType="nt:unstructured" 

                                sling:resourceType="granite/ui/components/coral/foundation/container"> 

                                <items jcr:primaryType="nt:unstructured"> 

                                    <multifieldcollection 

                                        jcr:primaryType="nt:unstructured" 

                                        sling:resourceType="granite/ui/components/coral/foundation/form/multifield" 

                                        composite="{Boolean}true" 

                                        fieldDescription="Click + to add a new item" 

                                        fieldLabel="Multifield collection" 

                                        name="./multiCol"> 

                                        <field 

                                            jcr:primaryType="nt:unstructured" 

                                            sling:resourceType="granite/ui/components/coral/foundation/container" 

                                            name="./demoItems"> 

                                            <items jcr:primaryType="nt:unstructured">

                                                <mfRef

                                                    jcr:primaryType="nt:unstructured"

                                                    sling:resourceType="granite/ui/components/foundation/form/hidden"

                                                    name="./mfRef"

                                                    granite:class="mf-ref"

                                                    value=""/>

                                                <title 

                                                    jcr:primaryType="nt:unstructured" 

                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield" 

                                                    fieldDescription="Add a title" 

                                                    fieldLabel="Title" 

                                                    name="./title"/> 

                                                <text 

                                                    jcr:primaryType="nt:unstructured" 

                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield" 

                                                    fieldDescription="Add Text" 

                                                    fieldLabel="Text" 

                                                    name="./text"/>

                                                <hasContainer

                                                    jcr:primaryType="nt:unstructured"

                                                    sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"

                                                    text="Include Container"

                                                    fieldDescription="Check this box to add a container"

                                                    name="./hasContainer"

                                                    value="{Boolean}true"

                                                    uncheckedValue="{Boolean}false"/>

                                            </items> 

                                        </field> 

                                    </multifieldcollection> 

                                </items> 

                            </column> 

                        </items> 

                    </Basic> 

                </items> 

            </tabs> 

        </items> 

    </content> 

</jcr:root>

DemoPanelSelector.java

package com.pnc.core.models;

import javax.inject.Inject;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.models.annotations.*;

@Model(

          adaptables = Resource.class,

          defaultInjectionStrategy=DefaultInjectionStrategy.OPTIONAL

)

public class DemoPanelSelector {

     @Inject

     private Resource demoItems;

     public Resource getDemoItems() {

          return demoItems;

     }

}

content.xml of component

<?xml version="1.0" encoding="UTF-8"?>

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"

cq:icon="panel"

    cq:isContainer="{Boolean}true"

    jcr:description="A Demo Component to test the PanelContainer selector in AEM"

    jcr:primaryType="cq:Component"

    jcr:title="Demo Panel Selector"

    componentGroup="PNC.COM Core Components"/>

Message was edited by: relaxabyte-corp

10 Replies

Avatar

Level 2

The code didn't seem to post. Here are screenshots from the "Edit" mode.

codeSample1.jpgcodeSample2.jpg

dialog

codeSample3.jpgcodeSample4.jpg

Avatar

Level 3

This seems quite useful for custom component development.

Following for answers.

Avatar

Level 2

Have so few people messed around with "Select Panel" to the editor toolbar? I realize that documentation is basically README.md files, github code, and crx nodes. The "Custom Component" was just a sample to see how the tool works. I'm not necessarily looking for a line-item debug. From the documentation that I could find, these were the things that I did:

  • I have the editorhook with panelcontainer.js to register it to panelcontainer.
  • I have the cq:editconfig set up with listeners.
  • I have the cq:Component set to isContainer.

What else is needed to pair the Panel Selector to a component? Are there more OOTB steps, or do I have to write custom event listeners at this point?

Thanks for looking at this with me.

@relaxabyte-corp : We are in need to incorporate the same in one of our custom-component? the editorhook is not working for the custom component..Did you got any solution yet?

Avatar

Level 2

I was able to get this feature working in a proxy component (custom component that extends the core component via resourceSuperType).  I was using Tabs, but it could be done the same way with Carousel.  The key is to define the markup selectors correctly in the clientlib file that gets executed on editor instantiation...

/*
 * Copy this to your proxy component, rather than allowing Sling Resource Merger to use the core component's version...
   /apps/core/wcm/components/tabs/v1/tabs/clientlibs/editorhook/*
And once the structure is copied, update the proxy component's file...
/apps/my-project/components/tabs/clientlibs/editorhook/js/panelcontainer.js */ (function(channel) { "use strict"; channel.on("cq-editor-loaded", function(event) { if (window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.panelcontainer && window.CQ.CoreComponents.panelcontainer.v1 && window.CQ.CoreComponents.panelcontainer.v1.registry) { window.CQ.CoreComponents.panelcontainer.v1.registry.register({ name: "cmp-tabs", selector: ".cmp-tabs", itemSelector: "[data-cmp-hook-tabs='tabpanel']", itemActiveSelector: ".cmp-tabs__tabpanel--active" }); } }); })(jQuery(document));


Make sure to update these values to match your markup as follows:

  • name: "cmp-tabs", // Your component's HTML wrapper needs the attribute "data-cmp-is" set to this name value, so jQuery can find it
  • selector: ".cmp-tabs", // Your component's HTML wrapper needs to meet the selector criteria, as jQuery will use this selector to look up the element and determine if it is a container that can have this "Select Panel" feature
  • itemSelector: "[data-cmp-hook-tabs='tabpanel']", // Your component's panel item selector, again used by jQuery
  • itemActiveSelector: ".cmp-tabs__tabpanel--active" // Your component's active item selector, again used by jQuery

If these selectors don't align with your markup, jQuery will have undefined matches and, in turn, this "Select Panel" feature will not be enabled.  Good luck!

Avatar

Level 1

Hey, I did this but still, core clientlibs get loaded (which is right coz the way clientlibs works). How did you resolve that issue?

- created clientlibs structure in custom component 

 - customized code for my need

 

But still, core-js also gets loaded along with my custom js but core-js creates the issue

Avatar

Level 1

Hi , 

I am also trying to use tabs for proxy component, but this doesnt work for me.

I have done following to make it work, I am not able to see default items and select panel 

  • editorhook with panelcontainer.js to register it to panelcontainer.
  • cq:editconfig set up with listeners.
  • cq:isContainer set to true.

is there anything else is required to get this done? 

Thanks in Advance.

Avatar

Level 2

Hi All,

I can not find in your snippets a subscription to panelcontainer messages:

window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
                    if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
...

This is from the core carousel sites js clientib. Seems that even though you provide the itemActiveSelector it is not automatically assigned to the selected panel item. You have to subscribe to cmp.panelcontainer messages and assign your active selector to the selected item.

Hope it helps.

 

 

Avatar

Level 2

I have this working on our Accordion, however, all it does is let us drag/drop to reorder the accordion sections.  This is fine by itself, but am I wrong to think it was supposed to ALSO expand the accordion, so we could add content into the sections?  It does NOT do  that, would love it to if it can.