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
