Goal
Create a component that uses a dropdown that shows/hides fields inside a multifield.
Procedure
Let’s create our dialog as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Component Configuration"
extraClientlibs="[lab2020.base.showhide-multifield]"
sling:resourceType="cq/gui/components/authoring/dialog">
<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="true">
<items jcr:primaryType="nt:unstructured">
<configuration
jcr:primaryType="nt:unstructured"
jcr:title="Configuration"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="true">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<slides
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
composite="{Boolean}true"
fieldLabel="Slides">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
name="./slides">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
granite:class="cmp-image__editor-alt-text"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./title"/>
<assetConfiguration
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="true">
<items jcr:primaryType="nt:unstructured">
<heading
granite:class="coral-Heading coral-Heading--4"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/heading"
level="{Long}4"
text="Asset Configuration"/>
<well
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/well">
<items jcr:primaryType="nt:unstructured">
<assetType
granite:class="cq-dialog-dropdown-showhide-multival"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Asset Type"
name="./assetType">
<granite:data
jcr:primaryType="nt:unstructured"
cq-dialog-dropdown-showhide-target=".list-option-listfrom-showhide-target-asset-type"/>
<items jcr:primaryType="nt:unstructured">
<image
jcr:primaryType="nt:unstructured"
text="Image"
value="image"/>
<video
jcr:primaryType="nt:unstructured"
text="Video"
value="video"/>
</items>
</assetType>
<setImage
granite:class="hide list-option-listfrom-showhide-target-asset-type foundation-layout-util-vmargin"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data
jcr:primaryType="nt:unstructured"
showhidetargetvalue="image"/>
<items jcr:primaryType="nt:unstructured">
<heading
granite:class="coral-Heading coral-Heading--4"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/heading"
level="{Long}4"
text="Options for Image"/>
<well
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/well">
<items jcr:primaryType="nt:unstructured">
<imageConfiguration
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<heading
granite:class="coral-Heading coral-Heading--4"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/heading"
level="{Long}4"
text="Image Configuration"/>
<well
jcr:primaryType="nt:unstructured"
margin="{Boolean}true"
sling:resourceType="granite/ui/components/coral/foundation/well">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<image
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
fieldLabel="Insert the Desktop Image"
rootPath="/content/dam"
name="./fileReference"/>
</items>
</column>
</items>
</well>
</items>
</imageConfiguration>
</items>
</well>
</items>
</setImage>
<setVideo
granite:class="hide list-option-listfrom-showhide-target-asset-type foundation-layout-util-vmargin"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data
jcr:primaryType="nt:unstructured"
showhidetargetvalue="video"/>
<items jcr:primaryType="nt:unstructured">
<heading
granite:class="coral-Heading coral-Heading--4"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/heading"
level="{Long}4"
text="Options for Video"/>
<well
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/well">
<items jcr:primaryType="nt:unstructured">
<videoId
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Video Id (Youtube Video)"
name="./videoId"
required="{Boolean}false">
</videoId>
</items>
</well>
</items>
</setVideo>
</items>
</well>
</items>
</assetConfiguration>
</items>
</column>
</items>
</field>
</slides>
</items>
</column>
</items>
</configuration>
</items>
</tabs>
</items>
</content>
</jcr:root>
This is a very simple dialog, it’s just to show you how it works. How to use it:
- add your clientlib category in the “extraClientlib” property, as shown above.
- add the class “cq-dialog-dropdown-showhide-multival” to your dropdown (see assetType)
- add the data attribute “cq-dialog-dropdown-showhide-multiple-target” to the dropdown/select element, value should be the selector, usually a specific class name, to find all possible target elements that can be shown/hidden (see assetType).
- add the target class to each target component that can be shown/hidden, add the class hidden to each target component to make them initially hidden and add the attribute showhidetargetvalue to each target component, the value(or commma separated multiple values e.g. val1, val2) should equal the value of the select. (see setImage and setVideo containers)
Now create the clientlib. Choose the category name you prefer and add the following JS file:
/**
* Extension to the standard dropdown/select component. It enabled hidding/unhidding of other components based on the
* selection made in the dropdown/select in multifield and multivalued.
*
* How to use:
*
* - add the class cq-dialog-dropdown-showhide-multival to the dropdown/select element
* - add the data attribute cq-dialog-dropdown-showhide-target to the dropdown/select element, value should be the
* selector, usually a specific class name, to find all possible target elements that can be shown/hidden.
* - add the target class to each target component that can be shown/hidden
* - add the class hidden to each target component to make them initially hidden
* - add the attribute showhidetargetvalue to each target component, the value(or commma separated multiple values e.g. val1, val2) should equal the value of the select
* option that will unhide this element.
*/
(function(document, $) {
"use strict";
// when dialog gets injected
$(document).on("foundation-contentloaded", function(e) {
// if there is already an inital value make sure the according target element becomes visible
showHideHandler($(".cq-dialog-dropdown-showhide-multival", e.target));
});
$(document).on("selected", ".cq-dialog-dropdown-showhide-multival", function(e) {
showHideHandler($(this));
});
function showHideHandler(el) {
el.each(function(i, element) {
if ($(element).is("coral-select")) {
// handle Coral3 base drop-down
Coral.commons.ready(element, function(component) {
showHide(component, element);
component.on("change", function() {
showHide(component, element);
});
});
} else {
// handle Coral2 based drop-down
var component = $(element).data("select");
if (component) {
showHide(component, element);
}
}
})
}
function showHide(component, element) {
// get the selector to find the target elements. its stored as data-.. attribute
var target = $(element).data("cqDialogDropdownShowhideTarget");
var $target = $(target);
var elementIndex = $(element).closest('coral-multifield-item').index();
if (target) {
var value;
if (component.value) {
value = component.value;
} else {
value = component.getValue();
}
$target.each(function(index) {
var tarIndex = $(this).closest('coral-multifield-item').index();
if (elementIndex == tarIndex) {
$(this).not(".hide").addClass("hide");
$(this).filter(function() {
return $(this).data('showhidetargetvalue').replace(/ /g, '').split(',').includes(value);
}).removeClass("hide");
}
});
}
}
})(document, Granite.$);
That’s all! This has been tested on AEM 6.5 but I’m pretty sure that can work on AEM 6.4 and 6.3.
Cheers! 🍻