Quantcast
Channel: Experiencing Adobe Experience Manager (AEM, CQ)
Viewing all articles
Browse latest Browse all 525

AEM 61 - Touch UI Composite Multifield Store Values as Child Nodes

$
0
0

Goal


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

For storing values as json check this post

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

Tested on AEM 61; should work ok on 60

Demo | Package Install


Composite Multifield in Dialog





Value Nodes in CRX





Dialog Structure






Dialog XML

Sample dialog with 3 composite multifields added in 3 tabs. #49, #125, #202 mark these multifields as composite, by specifying the flag eaem-nested

<?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="Multifield TouchUI Component"
sling:resourceType="cq/gui/components/authoring/dialog"
helpPath="en/cq/current/wcm/default_components.html#Text">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/tabs"
type="nav"/>
<items jcr:primaryType="nt:unstructured">
<india
jcr:primaryType="nt:unstructured"
jcr:title="India"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<fieldset
jcr:primaryType="nt:unstructured"
jcr:title="India Dashboard"
sling:resourceType="granite/ui/components/foundation/form/fieldset">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<dashboard
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Dashboard name"
fieldLabel="Dashboard"
name="./iDashboard"/>
<pages
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
class="full-width"
eaem-nested=""
fieldDescription="Click '+' to add a new page"
fieldLabel="URLs">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/fieldset"
name="./iItems">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
method="absolute"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<page
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Page Name"
fieldLabel="Page Name"
name="./page"/>
<path
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/pathbrowser"
fieldDescription="Select Path"
fieldLabel="Path"
name="./path"
rootPath="/content"/>
</items>
</column>
</items>
</field>
</pages>
</items>
</column>
</items>
</fieldset>
</items>
</column>
</items>
</india>
<usa
jcr:primaryType="nt:unstructured"
jcr:title="USA"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<fieldset
jcr:primaryType="nt:unstructured"
jcr:title="USA Dashboard"
sling:resourceType="granite/ui/components/foundation/form/fieldset">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<dashboard
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Dashboard name"
fieldLabel="Dashboard"
name="./uDashboard"/>
<pages
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
class="full-width"
eaem-nested=""
fieldDescription="Click '+' to add a new page"
fieldLabel="URLs">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/fieldset"
eaem-nested=""
name="./uItems">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
method="absolute"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<page
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Page Name"
fieldLabel="Page Name"
name="./page"/>
<path
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/pathbrowser"
fieldDescription="Select Path"
fieldLabel="Path"
name="./path"
rootPath="/content"/>
</items>
</column>
</items>
</field>
</pages>
</items>
</column>
</items>
</fieldset>
</items>
</column>
</items>
</usa>
<uk
jcr:primaryType="nt:unstructured"
jcr:title="UK"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<fieldset
jcr:primaryType="nt:unstructured"
jcr:title="UK Dashboard"
sling:resourceType="granite/ui/components/foundation/form/fieldset">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<dashboard
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Dashboard name"
fieldLabel="Dashboard"
name="./ukDashboard"/>
<pages
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
class="full-width"
eaem-nested=""
fieldDescription="Click '+' to add a new page"
fieldLabel="URLs">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/fieldset"
eaem-nested=""
name="./ukItems">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
method="absolute"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<page
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Page Name"
fieldLabel="Page Name"
name="./page"/>
<path
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/pathbrowser"
fieldDescription="Select Path"
fieldLabel="Path"
name="./path"
rootPath="/content"/>
</items>
</column>
</items>
</field>
</pages>
</items>
</column>
</items>
</fieldset>
</items>
</column>
</items>
</uk>
</items>
</content>
</jcr:root>


Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/touch-ui-composite-multi-field-store-as-child-nodes

2) Create clientlib (type cq:ClientLibraryFolder/apps/touch-ui-composite-multi-field-store-as-child-nodes/clientlib and set a property categories of String type to cq.authoring.dialogdependencies of type String[] with value underscore

3) Create file ( type nt:file ) /apps/touch-ui-composite-multi-field-store-as-child-nodes/clientlib/js.txt, add the following

                         multifield.js

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

(function () {
var DATA_EAEM_NESTED = "data-eaem-nested";
var CFFW = ".coral-Form-fieldwrapper";

//reads multifield data from server, creates the nested composite multifields and fills them
function addDataInFields() {
function getMultiFieldNames($multifields){
var mNames = {}, mName;

$multifields.each(function (i, multifield) {
mName = $(multifield).children("[name$='@Delete']").attr("name");

mName = mName.substring(0, mName.indexOf("@"));

mName = mName.substring(2);

mNames[mName] = $(multifield);
});

return mNames;
}

function buildMultiField(data, $multifield, mName){
if(_.isEmpty(mName) || _.isEmpty(data)){
return;
}

_.each(data, function(value, key){
if(key == "jcr:primaryType"){
return;
}

$multifield.find(".js-coral-Multifield-add").click();

_.each(value, function(fValue, fKey){
if(fKey == "jcr:primaryType"){
return;
}

var $field = $multifield.find("[name='./" + fKey + "']").last();

if(_.isEmpty($field)){
return;
}

$field.val(fValue);
});
});
}

$(document).on("dialog-ready", function() {
var $multifields = $("[" + DATA_EAEM_NESTED + "]");

if(_.isEmpty($multifields)){
return;
}

var mNames = getMultiFieldNames($multifields),
$form = $(".cq-dialog"),
actionUrl = $form.attr("action") + ".infinity.json";

$.ajax(actionUrl).done(postProcess);

function postProcess(data){
_.each(mNames, function($multifield, mName){
buildMultiField(data[mName], $multifield, mName);
});
}
});
}

//collect data from widgets in multifield and POST them to CRX
function collectDataFromFields(){
function fillValue($form, fieldSetName, $field, counter){
var name = $field.attr("name");

if (!name) {
return;
}

//strip ./
if (name.indexOf("./") == 0) {
name = name.substring(2);
}

//remove the field, so that individual values are not POSTed
$field.remove();

$('<input />').attr('type', 'hidden')
.attr('name', fieldSetName + "/" + counter + "/" + name)
.attr('value', $field.val())
.appendTo($form);
}

$(document).on("click", ".cq-dialog-submit", function () {
var $multifields = $("[" + DATA_EAEM_NESTED + "]");

if(_.isEmpty($multifields)){
return;
}

var $form = $(this).closest("form.foundation-form"),
$fieldSets, $fields;

$multifields.each(function(i, multifield){
$fieldSets = $(multifield).find("[class='coral-Form-fieldset']");

$fieldSets.each(function (counter, fieldSet) {
$fields = $(fieldSet).children().children(CFFW);

$fields.each(function (j, field) {
fillValue($form, $(fieldSet).data("name"), $(field).find("[name]"), (counter + 1));
});
});
});
});
}

$(document).ready(function () {
addDataInFields();
collectDataFromFields();
});
})();

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


Viewing all articles
Browse latest Browse all 525

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>