Tuesday, August 21, 2018

AEM 61 Classic UI Composite Multifield Storing Values as Nodes

AEM 61 Classic UI Composite Multifield Storing Values as Nodes


Goal


Create a Classic UI Composite Multifield, storing the composite field values as child nodes (useful when executing search queries for exact matches).

For storing values in json format, check this post

For Touch UI Composite Multifield storing values as child nodes check this post

Tested on AEM 61; should work ok on 60 and 561 too...  Demo | Package Install


Bug Fixes

Not working with selection drop downs in multifield - Demo | Package Install


Multi Field Panel



Value Nodes in CRX






Dialog in CRX




Dialog XML

#31, #37, #43 - property dName used in creating fully qualified name (./<multifield-name>/<order>/<dName>) eg ./stock/1/year

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root
jcr_primaryType="cq:Dialog"
title="Multi Field"
xtype="dialog">
<items
jcr_primaryType="cq:Widget"
xtype="tabpanel">
<items jcr_primaryType="cq:WidgetCollection">
<tab1
jcr_primaryType="cq:Panel"
title="Add">
<items jcr_primaryType="cq:WidgetCollection">
<stock
jcr_primaryType="cq:Widget"
hideLabel="false"
name="./stock"
title="Stock"
xtype="multifield">
<fieldConfig
jcr_primaryType="cq:Widget"
border="true"
hideLabel="true"
layout="form"
padding="10px"
width="1000"
xtype="multi-field-panel">
<items jcr_primaryType="cq:WidgetCollection">
<product-year-value
jcr_primaryType="cq:Widget"
dName="year"
fieldLabel="Year"
width="60"
xtype="textfield"/>
<product-price-value
jcr_primaryType="cq:Widget"
dName="price"
fieldLabel="Price"
width="60"
xtype="textfield"/>
<product-version-value
jcr_primaryType="cq:Widget"
dName="version"
fieldLabel="Path to Version"
xtype="pathfield"/>
</items>
</fieldConfig>
</stock>
</items>
</tab1>
</items>
</items>
</jcr:root>


Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/classic-ui-multi-field-panel-node-store

2) Create clientlib (type cq:ClientLibraryFolder/apps/classic-ui-multi-field-panel-node-store/clientlib and set a property categories of String type to cq.widgets

3) Create file ( type nt:file ) /apps/classic-ui-multi-field-panel-node-store/clientlib/js.txt, add the following

                         multi-field.js

4) Create file ( type nt:file ) /apps/classic-ui-multi-field-panel-node-store/clientlib/multi-field.js, add the following code

CQ.Ext.ns("ExperienceAEM");

ExperienceAEM.MultiFieldPanel = CQ.Ext.extend(CQ.Ext.Panel, {
constructor: function(config){
config = config || {};
ExperienceAEM.MultiFieldPanel.superclass.constructor.call(this, config);
},

initComponent: function () {
ExperienceAEM.MultiFieldPanel.superclass.initComponent.call(this);

function addName(items, prefix, counter){
items.each(function(i){
if(!i.hasOwnProperty("dName")){
return;
}

i.name = prefix + "/" + (counter) + "/" + i.dName;

if(i.el && i.el.dom){ //form serialization workaround
i.el.dom.name = prefix + "/" + (counter) + "/" + i.dName;
}
},this);
}

var multi = this.findParentByType("multifield"),
multiPanels = multi.findByType("multi-field-panel");

addName(this.items, this.name, multiPanels.length + 1);

multi.on("removeditem", function(){
multiPanels = multi.findByType("multi-field-panel");

for(var x = 1; x <= multiPanels.length; x++){
addName(multiPanels[x-1].items, multiPanels[x-1].name, x);
}
});
},

afterRender : function(){
ExperienceAEM.MultiFieldPanel.superclass.afterRender.call(this);

this.items.each(function(){
if(!this.contentBasedOptionsURL
|| this.contentBasedOptionsURL.indexOf(CQ.form.Selection.PATH_PLACEHOLDER) < 0){
return;
}

this.processPath(this.findParentByType(dialog).path);
})
},

getValue: function () {
var pData = {};

this.items.each(function(i){
if(!i.hasOwnProperty("dName")){
return;
}

pData[i.dName] = i.getValue();
});

return pData;
},

setValue: function (value) {
var counter = 1, item,
multi = this.findParentByType("multifield"),
multiPanels = multi.findByType("multi-field-panel");

if(multiPanels.length == 1){
item = value[counter];
}else{
item = value;
}

this.items.each(function(i){
if(!i.hasOwnProperty("dName")){
return;
}

i.setValue(item[i.dName]);
});

if(multiPanels.length == 1){
while(true){
item = value[++counter];

if(!item){
break;
}

multi.addItem(item);
}
}
},

validate: function(){
return true;
},

getName: function(){
return this.name;
}
});

CQ.Ext.reg("multi-field-panel", ExperienceAEM.MultiFieldPanel);

5) A sample exact match query performed with query builder, on property name year, returning multifield nodes

http://localhost:4502/bin/querybuilder.json?property=year&property.value=2010&p.hits=full




visit link download