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 xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" 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
Hi Sreekanth, I am facing one issue with the Package Install given here. Here is the scenario:
ReplyDelete- I add 1st set of entries on Dialog.
- I put values in them.
- I add 2nd set of entries, keep them blank
- I try to move the 2nd set to the first position
- The 2nd set moves up, but the values for blank fields get populated from the 1st set.
- This is happening for the Move Down icon button also.
Can you please help me with a fix ?
Are you sure? this demo is on 61 https://drive.google.com/file/d/0B4d6KmbLkAumV2tmSldNYS1MM1E/view?usp=sharing
DeleteHi Sreekanth ,
ReplyDeleteIf I further needs to store path , price , and value as nodes instead of the properties , how can I achieve this? I have a requirement where in my multifield I have two pathfields ( one for hero image) and one for thumbnail image. Now I want to store each of the properties as a separate node inside node 1 and node 2 so that I can use image servlet to render my dam images .
1/heroImage/fileReference = path to hero image
1/heroImage/sling:resourceType = ‘foundation/components/image’
1/thumbnailImage/fileReference = path to thumbnail image
1/thumbnailImage/sling:resourceType = ‘foundation/components/image’
…then paths to the image servlets would be:
./1/heroImage.img.png
./1/thumbnailImage.img.png
Please advise. Also , is it really worth to write a custom xtype just to render dam images using image servlet and not using direct dam asset path from path field.
Dg, you should check http://experience-aem.blogspot.com/2014/04/aem-cq-56-slide-show-component.html
DeleteHi Sreekanth,
ReplyDeleteNodes are not creating for Drop down fields. I need to store the drop down values as well. For example image left align true/false;
Can you please help me to fix this issue?
Thanks,
Syam
syam, can you upload the component zip to dropbox/gdrive and share the link here...
DeleteSreekanth, sorry for late response. Here is the link https://drive.google.com/file/d/0B5r-Uc8tQnYURTVCY0trT1R0a0k/view?usp=sharing
DeleteSreekanth, Please let me is there any fix for it.
Deletesyam,check the bugfixes section above
DeleteThank you very much Sreekanth..
DeleteHi Sreekanth, would you be able to help make it support for both xtype=selection, type=radiogroup and xtype=selection, type=checkbox?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteIf you are having issues with the node data displaying in the dialog (after saving and refreshing), try adding a "name" property with "./[same as dName]".
ReplyDeleteMy data was saved in CRX, but the dialog would just show an empty box for each node. This fixed my issue running 6.2
Hi Sreekanth, What if i need to add fieldset in it and have some properties under it . so it is not saving the data in jcr nodes
ReplyDeleteThis comment has been removed by the author.
ReplyDelete