Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

Nested multifield in AEM 6.3 + sightly

anoopo70540109
Level 2
Level 2

Multifield 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="List Collection"

    sling:resourceType="cq/gui/components/authoring/dialog">

    <content

        jcr:primaryType="nt:unstructured"

        sling:resourceType="granite/ui/components/coral/foundation/container">

        <items jcr:primaryType="nt:unstructured">

            <tabs

                jcr:primaryType="nt:unstructured"

                sling:resourceType="granite/ui/components/coral/foundation/tabs"

                maximized="{Boolean}true">

                <items jcr:primaryType="nt:unstructured">

                    <Basic

                        jcr:primaryType="nt:unstructured"

                        jcr:title="Basic"

                        sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"

                        margin="{Boolean}false">

                        <items jcr:primaryType="nt:unstructured">

                            <column

                                jcr:primaryType="nt:unstructured"

                                sling:resourceType="granite/ui/components/coral/foundation/container">

                                <items jcr:primaryType="nt:unstructured">

                                    <enterheadline

                                        jcr:primaryType="nt:unstructured"

                                        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"

                                        fieldDescription="Please enter headline"

                                        fieldLabel="Enter Headline"

                                        name="./headlineText"/>

                                    <headingurl

                                        jcr:primaryType="nt:unstructured"

                                        sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"

                                        fieldDescription="Select Link Path"

                                        fieldLabel="Link Url"

                                        name="./headingUrl"/>

                                    <menu

                                        jcr:primaryType="nt:unstructured"

                                        sling:resourceType="granite/ui/components/foundation/form/multifield"

                                        composite="{Boolean}true"

                                        fieldDescription="Click + to add a new page"

                                        fieldLabel="Multifield collection"

                                        name="./menu">

                                        <field

                                            jcr:primaryType="nt:unstructured"

                                            sling:resourceType="granite/ui/components/foundation/form/fieldset"

                                            multifield-nested=""

                                            name="./items">

                                            <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">

                                                        <linkurl

                                                            jcr:primaryType="nt:unstructured"

                                                            sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"

                                                            fieldDescription="Select Link Path"

                                                            fieldLabel="Link Url"

                                                            name="./linkUrl"/>

                                                        <enterlinktext

                                                            jcr:primaryType="nt:unstructured"

                                                            sling:resourceType="granite/ui/components/coral/foundation/form/textfield"

                                                            fieldDescription="Enter Link Text"

                                                            fieldLabel="Enter link text"

                                                            name="./linkText"/>

                                                        <submenu

                                                            jcr:primaryType="nt:unstructured"

                                                            sling:resourceType="granite/ui/components/foundation/form/multifield"

                                                            fieldDescription="Add upto 14 links"

                                                            fieldLabel="Submenus"

                                                            name="./submenussss">

                                                            <field

                                                                jcr:primaryType="nt:unstructured"

                                                                sling:resourceType="granite/ui/components/foundation/form/fieldset"

                                                                name="./submenu">

                                                                <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">

                                                                            <url

                                                                                jcr:primaryType="nt:unstructured"

                                                                                sling:resourceType="granite/ui/components/foundation/form/pathbrowser"

                                                                                allowBlank="false"

                                                                                fieldLabel="Provide navigation link for text"

                                                                                key="url"

                                                                                name="./subUrl"/>

                                                                            <title

                                                                                jcr:primaryType="nt:unstructured"

                                                                                sling:resourceType="granite/ui/components/foundation/form/textfield"

                                                                                allowBlank="false"

                                                                                fieldLabel="Provide navigation text"

                                                                                key="title"

                                                                                maxLength="16"

                                                                                maxLengthText="A maximum of 16 characters is allowed for navigation text"

                                                                                name="./subTitle"/>

                                                                        </items>

                                                                    </column>

                                                                </items>

                                                            </field>

                                                        </submenu>

                                                    </items>

                                                </column>

                                            </items>

                                        </field>

                                    </menu>

                                </items>

                            </column>

                        </items>

                    </Basic>

                </items>

            </tabs>

        </items>

    </content>

</jcr:root>

navigation.js

"use strict";

use(function () {

    var readJson = null;

    var listArr = [];

    if (this.fieldValue != '') {

        readJson = this.fieldValue;

        var count = 0;

        if (readJson != null && readJson != "") {

            readJson.forEach(function (entry) {

                var itemJson = entry;

                listArr[count++] = itemJson;

            });

        }

    } else if (this.fieldName != '') {

        readJson = granite.resource.properties[this.fieldName];

        if (typeof readJson != "undefined" && readJson != null && readJson != "") {

            if (readJson.length > 0) {

                var count = 0;

                readJson.forEach(function (entry) {

                    var itemJson = JSON.parse(entry);

                    listArr[count++] = itemJson;

                });

            } else {

                listArr[0] = JSON.parse(readJson);

            }

        }

    }

    return {

        listJson: listArr

    }

});

Sightly: somecomponent.html

<sly data-sly-use.menuInfo="${'navigation.js' @ fieldName = 'items',fieldValue = ''}">

                        <sly data-sly-list.menuDetails="${menuInfo.listJson}">

<li><a href="${menuDetails.linkUrl}">${menuDetails.linkText}</a>

<ul>

                                <sly data-sly-use.submenuInfo="${'navigation.js' @ fieldName = '',fieldValue = menuDetails.submenu}">

                                <sly data-sly-list.innerlistJson="${submenuInfo.listJson}">

${innerlistJson.subTitle}</span></a></li>

</sly>

                                </sly>

                                </ul>

</li>

</sly>

                        </sly>

I have created this without using ACS-common package. hope it will helpful for the community

0 Replies
neilbertm664043
Level 4
Level 4

the add button for multifield node which is menu

slingResourceType: granite/ui/components/foundation/form/multifield - add button not working

sling:resourceType="granite/ui/components/coral/foundation/form/multifield" - add button working but the Ok/Submit button not working

anoopo70540109
Level 2
Level 2

(function () {

  var DATA_NESTED = "data-multifield-nested";

  var CFFW = ".coral-Form-fieldwrapper";

  //reads multifield data from server, creates the nested composite multifields and fills them

  function addDataInFields() {

    $(document).on("dialog-ready", function () {

      var $fieldSets = $("[" + DATA_NESTED + "][class='coral-Form-fieldset']");

      if (_.isEmpty($fieldSets)) {

        return;

      }

      var mNames = [];

      $fieldSets.each(function (i, fieldSet) {

        mNames.push($(fieldSet).data("name"));

      });

      mNames = _.uniq(mNames);

      var actionUrl = $fieldSets.closest("form.foundation-form").attr("action") + ".json";

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

      function postProcess(data) {

        _.each(mNames, function (mName) {

          buildMultiField(data, mName);

        });

      }

      //creates & fills the nested multifield with data

      function fillNestedFields($multifield, valueArr) {

        _.each(valueArr, function (record, index) {

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

          //a setTimeout may be needed

          _.each(record, function (value, key) {

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

            $field.val(value);

          });

        });

      }

      function buildMultiField(data, mName) {

        if (_.isEmpty(mName)) {

          return;

        }

        $fieldSets = $("[data-name='" + mName + "']");

        mName = mName.substring(2);

        var mValues = data[mName], $field, name;

        if (_.isString(mValues)) {

          mValues = [JSON.parse(mValues)];

        }

        _.each(mValues, function (record, i) {

          if (!record) {

            return;

          }

          if (_.isString(record)) {

            record = JSON.parse(record);

          }

          _.each(record, function (rValue, rKey) {

            $field = $($fieldSets[i]).find("[name='./" + rKey + "']");

            if (_.isArray(rValue) && !_.isEmpty(rValue)) {

              fillNestedFields($($fieldSets[i]).find("[data-init='multifield']"), rValue);

            } else {

              $field.val(rValue);

            }

          });

        });

      }

    });

  }

  function fillValue($field, record) {

    var name = $field.attr("name");

    if (!name) {

      return;

    }

    //strip ./

    if (name.indexOf("./") === 0) {

      name = name.substring(2);

    }

    record[name] = $field.val();

    //remove the field, so that individual values are not POSTed

    //$field.remove();

  }

  //for getting the nested multifield data as js objects

  function getRecordFromMultiField($multifield) {

    var $fieldSets = $multifield.find("[class='coral-Form-fieldset']");

    var records = [], record, $fields, name;

    $fieldSets.each(function (i, fieldSet) {

      $fields = $(fieldSet).find("[name]");

      record = {};

      $fields.each(function (j, field) {

        fillValue($(field), record);

      });

      if (!$.isEmptyObject(record)) {

        records.push(record);

      }

    });

    return records;

  }

  //collect data from widgets in multifield and POST them to CRX as JSON

  function collectDataFromFields() {

    $(document).on("click", ".cq-dialog-submit", function () {

      var fieldd = $(".coral-Multifield");

      var sizee = fieldd.attr("data-minlinksallowed");

      if (sizee) {

        var uii = $(window).adaptTo("foundation-ui");

        var totalLinkCount = $(".coral-Multifield-list li").length;

        if (totalLinkCount < sizee) {

          uii.alert("Minimum " + sizee + " fields are required");

          return false;

        }

      }

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

      $form.find('input.input-mf-data').each(function(){

        $(this).remove();

      });

      var $fieldSets = $("[" + DATA_NESTED + "][class='coral-Form-fieldset']");

      var record, $fields, $field, name, $nestedMultiField;

      $fieldSets.each(function (i, fieldSet) {

        $fields = $(fieldSet).children().children(CFFW);

        record = {};

        $fields.each(function (j, field) {

          $field = $(field);

          //may be a nested multifield

          $nestedMultiField = $field.find("[data-init='multifield']");

          if ($nestedMultiField.length === 0) {

            fillValue($field.find("[name]"), record);

          } else {

            name = $nestedMultiField.find("[class='coral-Form-fieldset']").data("name");

            if (!name) {

              return;

            }

            //strip ./

            name = name.substring(2);

            record[name] = getRecordFromMultiField($nestedMultiField);

          }

        });

        if ($.isEmptyObject(record)) {

          return;

        }

        //add the record JSON in a hidden field as string

          $('<input />').attr('type', 'hidden')

            .attr('class', 'input-mf-data')

            .attr('name', $(fieldSet).data("name"))

            .attr('value', JSON.stringify(record))

            .appendTo($form);

      });

      return true;

    });

  }

  $(document).ready(function () {

    addDataInFields();

    collectDataFromFields();

  });

  $(document).on("dialog-ready", function () {

    $(".js-coral-Multifield-add").click(function () {

      var field = $(this).parent();

      var size = field.attr("data-limit");

      if (size) {

        var ui = $(window).adaptTo("foundation-ui");

        var totalLinkCount = $(this).prev('ol').children('li').length;

        if (totalLinkCount >= size) {

          ui.alert("Warning", "Only " + totalLinkCount + " fields are allowed!", "notice");

          return false;

        }

      }

    });

  });

  //extend otb multifield for adjusting event propagation when there are nested multifields

  //for working around the nested multifield add and reorder

  CUI.MultifieldProject = new Class({

    toString: "Multifield",

    extend: CUI.Multifield,

    construct: function (options) {

      this.script = this.$element.find(".js-coral-Multifield-input-template:last");

    },

    _addListeners: function () {

      this.superClass._addListeners.call(this);

      //otb coral event handler is added on selector .js-coral-Multifield-add

      //any nested multifield add click events are propagated to the parent multifield

      //to prevent adding a new composite field in both nested multifield and parent multifield

      //when user clicks on add of nested multifield, stop the event propagation to parent multifield

      this.$element.on("click", ".js-coral-Multifield-add", function (e) {

        e.stopPropagation();

      });

      this.$element.on("drop", function (e) {

        e.stopPropagation();

      });

    }

  });

  CUI.Widget.registry.register("multifield", CUI.MultifieldProject);

})();

(function () {

  var DATA_NESTED = "data-multifield-nested";

  var CFFW = ".coral-Form-fieldwrapper";

  //reads multifield data from server, creates the nested composite multifields and fills them

  function addDataInFields() {

    $(document).on("dialog-ready", function () {

      var $fieldSets = $("[" + DATA_NESTED + "][class='coral-Form-fieldset']");

      if (_.isEmpty($fieldSets)) {

        return;

      }

      var mNames = [];

      $fieldSets.each(function (i, fieldSet) {

        mNames.push($(fieldSet).data("name"));

      });

      mNames = _.uniq(mNames);

      var actionUrl = $fieldSets.closest("form.foundation-form").attr("action") + ".json";

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

      function postProcess(data) {

        _.each(mNames, function (mName) {

          buildMultiField(data, mName);

        });

      }

      //creates & fills the nested multifield with data

      function fillNestedFields($multifield, valueArr) {

        _.each(valueArr, function (record, index) {

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

          //a setTimeout may be needed

          _.each(record, function (value, key) {

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

            $field.val(value);

          });

        });

      }

      function buildMultiField(data, mName) {

        if (_.isEmpty(mName)) {

          return;

        }

        $fieldSets = $("[data-name='" + mName + "']");

        mName = mName.substring(2);

        var mValues = data[mName], $field, name;

        if (_.isString(mValues)) {

          mValues = [JSON.parse(mValues)];

        }

        _.each(mValues, function (record, i) {

          if (!record) {

            return;

          }

          if (_.isString(record)) {

            record = JSON.parse(record);

          }

          _.each(record, function (rValue, rKey) {

            $field = $($fieldSets[i]).find("[name='./" + rKey + "']");

            if (_.isArray(rValue) && !_.isEmpty(rValue)) {

              fillNestedFields($($fieldSets[i]).find("[data-init='multifield']"), rValue);

            } else {

              $field.val(rValue);

            }

          });

        });

      }

    });

  }

  function fillValue($field, record) {

    var name = $field.attr("name");

    if (!name) {

      return;

    }

    //strip ./

    if (name.indexOf("./") === 0) {

      name = name.substring(2);

    }

    record[name] = $field.val();

    //remove the field, so that individual values are not POSTed

    //$field.remove();

  }

  //for getting the nested multifield data as js objects

  function getRecordFromMultiField($multifield) {

    var $fieldSets = $multifield.find("[class='coral-Form-fieldset']");

    var records = [], record, $fields, name;

    $fieldSets.each(function (i, fieldSet) {

      $fields = $(fieldSet).find("[name]");

      record = {};

      $fields.each(function (j, field) {

        fillValue($(field), record);

      });

      if (!$.isEmptyObject(record)) {

        records.push(record);

      }

    });

    return records;

  }

  //collect data from widgets in multifield and POST them to CRX as JSON

  function collectDataFromFields() {

    $(document).on("click", ".cq-dialog-submit", function () {

      var fieldd = $(".coral-Multifield");

      var sizee = fieldd.attr("data-minlinksallowed");

      if (sizee) {

        var uii = $(window).adaptTo("foundation-ui");

        var totalLinkCount = $(".coral-Multifield-list li").length;

        if (totalLinkCount < sizee) {

          uii.alert("Minimum " + sizee + " fields are required");

          return false;

        }

      }

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

      $form.find('input.input-mf-data').each(function(){

        $(this).remove();

      });

      var $fieldSets = $("[" + DATA_NESTED + "][class='coral-Form-fieldset']");

      var record, $fields, $field, name, $nestedMultiField;

      $fieldSets.each(function (i, fieldSet) {

        $fields = $(fieldSet).children().children(CFFW);

        record = {};

        $fields.each(function (j, field) {

          $field = $(field);

          //may be a nested multifield

          $nestedMultiField = $field.find("[data-init='multifield']");

          if ($nestedMultiField.length === 0) {

            fillValue($field.find("[name]"), record);

          } else {

            name = $nestedMultiField.find("[class='coral-Form-fieldset']").data("name");

            if (!name) {

              return;

            }

            //strip ./

            name = name.substring(2);

            record[name] = getRecordFromMultiField($nestedMultiField);

          }

        });

        if ($.isEmptyObject(record)) {

          return;

        }

        //add the record JSON in a hidden field as string

          $('<input />').attr('type', 'hidden')

            .attr('class', 'input-mf-data')

            .attr('name', $(fieldSet).data("name"))

            .attr('value', JSON.stringify(record))

            .appendTo($form);

      });

      return true;

    });

  }

  $(document).ready(function () {

    addDataInFields();

    collectDataFromFields();

  });

  $(document).on("dialog-ready", function () {

    $(".js-coral-Multifield-add").click(function () {

      var field = $(this).parent();

      var size = field.attr("data-limit");

      if (size) {

        var ui = $(window).adaptTo("foundation-ui");

        var totalLinkCount = $(this).prev('ol').children('li').length;

        if (totalLinkCount >= size) {

          ui.alert("Warning", "Only " + totalLinkCount + " fields are allowed!", "notice");

          return false;

        }

      }

    });

  });

  //extend otb multifield for adjusting event propagation when there are nested multifields

  //for working around the nested multifield add and reorder

  CUI.MultifieldProject = new Class({

    toString: "Multifield",

    extend: CUI.Multifield,

    construct: function (options) {

      this.script = this.$element.find(".js-coral-Multifield-input-template:last");

    },

    _addListeners: function () {

      this.superClass._addListeners.call(this);

      //otb coral event handler is added on selector .js-coral-Multifield-add

      //any nested multifield add click events are propagated to the parent multifield

      //to prevent adding a new composite field in both nested multifield and parent multifield

      //when user clicks on add of nested multifield, stop the event propagation to parent multifield

      this.$element.on("click", ".js-coral-Multifield-add", function (e) {

        e.stopPropagation();

      });

      this.$element.on("drop", function (e) {

        e.stopPropagation();

      });

    }

  });

  CUI.Widget.registry.register("multifield", CUI.MultifieldProject);

})();

arpitas
Level 1
Level 1

This solution is not working in  coral3 for aem6.3 migration. In coral 3 multifield tenplate is different so this js doesnt work.

Arun_Patidar
Community Advisor
Community Advisor

Hi,

In Coral3, multifields items are store as a node not as JSON, To make it work this with Js or Java, you can iterate through nodes and return as JSON array or java Arraylist.

namitkochar
Level 2
Level 2

Using aem 6.3 service pack and cummulative fix pack, multiield of 'n' number of levels can be added in AEM 6.3.

  1. AEM 6.3 Cumulative Fix Pack (https://helpx.adobe.com/experience-manager/release-notes--aem-6-3-cumulative-fix-pack.html#DownloadI...)
  2. AEM 6.3.3.0 Service Pack (https://helpx.adobe.com/experience-manager/6-3/release-notes/sp3-release-notes.html#Install6330)