Goal
Extend the product Composite Multifield to provide Expand / Collapse feature, for better experience and easy reordering
For 64 check this post
Demo | Package Install | Github
All Items Collapsed
One Item Expanded
Easy Reordering
Solution
1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-touchui-collapsible-multifield
2) Sample dialog with composite multifield /apps/eaem-touchui-collapsible-multifield/sample-collapsible-multifield/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" jcr:primaryType="nt:unstructured" jcr:title="63 Collapsible Multifield" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <products jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/multifield" composite="{Boolean}true" eaem-show-on-collapse="EAEM.showProductName" fieldLabel="Products"> <field jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container" name="./products"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <product jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldDescription="Name of Product" fieldLabel="Product Name" name="./product"/> <path jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/pathbrowser" fieldDescription="Select Path" fieldLabel="Path" name="./path" rootPath="/content"/> <startDate jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/datepicker" class="field" displayedFormat="YYYY-MM-DD HH:mm" fieldLabel="Start Date" name="./startDate" type="datetime"/> <show jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/checkbox" name="./show" text="Show?" value="yes"/> <type jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/select" fieldDescription="Select Size" fieldLabel="Size" name="./size"> <items jcr:primaryType="nt:unstructured"> <def jcr:primaryType="nt:unstructured" text="Select Size" value=""/> <small jcr:primaryType="nt:unstructured" text="Small" value="small"/> <medium jcr:primaryType="nt:unstructured" text="Medium" value="medium"/> <large jcr:primaryType="nt:unstructured" text="Large" value="large"/> </items> </type> </items> </column> </items> </field> </products> </items> </column> </items> </content> </jcr:root>
3) #14 eaem-show-on-collapse property is for the function creating summary of multifield items in collapsed mode; here it is EAEM.showProductName, returns the first field value in multifield item (if empty or error in creating summary Click to expand text is shown)
4) Create node /apps/eaem-touchui-collapsible-multifield/clientlib of type cq:ClientLibraryFolder, add String property categories with value cq.authoring.dialog.all, String property dependencies with value underscore
5) Create file (nt:file) /apps/eaem-touchui-collapsible-multifield/clientlib/js.txt, add
collapsible-multifield.js
6) Create file (nt:file) /apps/eaem-touchui-collapsible-multifield/clientlib/collapsible-multifield.js, add the following code
(function(){ if(typeof EAEM === "undefined"){ EAEM = {}; } //the function executed when user clicks collapse; returns summary of multifield item data EAEM.showProductName = function(fields){ return Object.values(fields)[0]; } }()); (function ($, $document, gAuthor) { var summaryCreators = {}, CORAL_MULTIFIELD = "coral-multifield", CORAL_MULTIFIELD_ITEM = "coral-multifield-item", CORAL_MULTIFIELD_ITEM_CONTENT = "coral-multifield-item-content", EAEM_SHOW_ON_COLLAPSE = "eaem-show-on-collapse", RS_MULTIFIELD = "granite/ui/components/coral/foundation/form/multifield"; $document.on("dialog-ready", addCollapsers); function addCollapsers(){ var $multifields = $(CORAL_MULTIFIELD).css("padding-right", "2.5rem"); if(_.isEmpty($multifields)){ return; } $multifields.find(CORAL_MULTIFIELD_ITEM).each(handler); $multifields.on('change', function(){ $multifields.find(CORAL_MULTIFIELD_ITEM).each(handler); }); loadShowSummaryCreatorFunctions(); addExpandCollapseAll($multifields); function handler(){ var $mfItem = $(this); if(!_.isEmpty($mfItem.find("[icon=accordionUp]"))){ return; } addAccordionIcons($mfItem); addSummarySection($mfItem); } } function addSummarySection($mfItem){ var $summarySection = $("<div/>").insertAfter($mfItem.find(CORAL_MULTIFIELD_ITEM_CONTENT)) .addClass("coral-Well").css("cursor", "pointer").hide(); $summarySection.click(function(){ $mfItem.find("[icon='accordionDown']").click(); }); } function addExpandCollapseAll($multifields){ var $mfAdd, expandAll, collapseAll; $multifields.find("[coral-multifield-add]").each(handler); function handler(){ $mfAdd = $(this); expandAll = new Coral.Button().set({ variant: 'secondary', innerText: "Expand All" }); expandAll.$.css("margin-left", "10px").click(function(){ event.preventDefault(); $(this).closest(CORAL_MULTIFIELD).find("[icon='accordionDown']").click(); }); collapseAll = new Coral.Button().set({ variant: 'secondary', innerText: "Collapse All" }); collapseAll.$.css("margin-left", "10px").click(function(){ event.preventDefault(); $(this).closest(CORAL_MULTIFIELD).find("[icon='accordionUp']").click(); }); $mfAdd.after(expandAll).after(collapseAll); } } function loadShowSummaryCreatorFunctions(){ var editable = gAuthor.DialogFrame.currentDialog.editable; if(!editable){ return; } $.ajax(editable.config.dialog + ".infinity.json").done(fillLabelCreatorFns); function fillLabelCreatorFns(obj){ if(!_.isObject(obj) || _.isEmpty(obj)){ return; } _.each(obj, function(value){ if(value["sling:resourceType"] === RS_MULTIFIELD){ if(!_.isEmpty(value.field) && !_.isEmpty(value.field.name)) { summaryCreators[value.field.name] = value[EAEM_SHOW_ON_COLLAPSE]; } }else{ if(_.isObject(value) && !_.isEmpty(value)){ fillLabelCreatorFns(value); } } }); } } function addAccordionIcons($mfItem){ var up = new Coral.Button().set({ variant: "quiet", icon: "accordionUp", title: "Collapse" }); up.setAttribute('style', 'position:absolute; top: 0; right: -2.175rem'); up.$.on('click', handler); $mfItem.append(up); var down = new Coral.Button().set({ variant: "quiet", icon: "accordionDown", title: "Expand" }); down.setAttribute('style', 'position:absolute; top: 0; right: -2.175rem'); down.$.on('click', handler).hide(); $mfItem.append(down); function handler(event){ event.preventDefault(); var mfName = $(this).closest(CORAL_MULTIFIELD).attr("data-granite-coral-multifield-name"), $mfItem = $(this).closest(CORAL_MULTIFIELD_ITEM), $summarySection = $mfItem.children("div"); $summarySection.html(getSummary($mfItem, mfName)); adjustUI.call(this, $summarySection); } function adjustUI($summarySection){ var icon = $(this).find("coral-icon").attr("icon"), $content = $mfItem.find(CORAL_MULTIFIELD_ITEM_CONTENT); if(icon == "accordionUp"){ if($summarySection.css("display") !== "none"){ return; } $summarySection.show(); $content.slideToggle( "fast", function() { $content.hide(); }); up.$.hide(); down.$.show(); }else{ if($summarySection.css("display") === "none"){ return; } $summarySection.hide(); $content.slideToggle( "fast", function() { $content.show(); }); up.$.show(); down.$.hide(); } } } function getSummary($mfItem, mfName){ var summary = "Click to expand"; try{ if(summaryCreators[mfName]){ var fields = {}; $mfItem.find("input").each(function(){ var $input = $(this); fields[$input.attr("name")] = $input.val(); }); summary = eval(summaryCreators[mfName])(fields); } }catch(err){} if(!summary){ summary = "Click to expand"; } return summary; } }(jQuery, jQuery(document), Granite.author));
I guess we can skip the customization if we use the collapsible layout: https://docs.adobe.com/docs/en/aem/6-3/develop/ref/granite-ui/api/jcr_root/libs/granite/ui/components/foundation/layouts/collapsible/index.html In my previous project it worked for us to add collapsible feature to multifields and nested multifields.
ReplyDeletecould you please post multifield limit in AEM 6.3
ReplyDeletehello ! pathbrowser in multifield don't click to Browse !
ReplyDeleteI copy your code and run on localhost !
hi , How can be make content fragment form Collapsible and Expandible grouping certain elements.
ReplyDeletethis function not working for me im using in 6.4.4 version can you share a valid one please
ReplyDelete