Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

at least one multifield should be available on dialog load

Avatar

Level 4

Hi Team,

I have a dialog where i am allowing authors to input data via multifield. Authors can add n numbers of multifield as per requirements.

Now my problem is, when authors open the dialog of my component, i want atleast one multifield to be available if there is no data available.

Please help.

1 Accepted Solution

Avatar

Correct answer by
Level 7

Hi,

Assuming that you're using sling:resourceType as "granite/ui/components/foundation/form/fieldset", please use the following JS logic (nested-multifield.js here) that creates and fills the nested multifield with one multifield item open by default on dialog load. The highlighted lines of code in the below js file is responsible for populating one multifield item open by default if there is no data available.

nested-multifield.js:

(function ($, $document) {

    var EAEM_NESTED = "eaem-nested",

        DATA_EAEM_NESTED = "data-" + EAEM_NESTED,

        CFFW = ".coral-Form-fieldwrapper",

        NODE_STORE = "NODE_STORE";

    if(CUI.Multifield.eaemNMFExtended){

        return;

    }

    CUI.Multifield.eaemNMFExtended = true;

    function isNodeStoreMultifield(type) {

        return (type === NODE_STORE);

    }

    function isSelectOne($field) {

        return !_.isEmpty($field) && ($field.prop("type") === "select-one");

    }

    function setSelectOne($field, value) {

        var select = $field.closest(".coral-Select").data("select");

        if (select) {

            select.setValue(value);

        }

    }

    function isCheckbox($field) {

        return !_.isEmpty($field) && ($field.prop("type") === "checkbox");

    }

    function setCheckBox($field, value) {

        $field.prop("checked", $field.attr("value") === value);

    }

    function isDateField($field) {

        return !_.isEmpty($field) && $field.parent().hasClass("coral-DatePicker");

    }

    function setDateField($field, value) {

        var date = moment(new Date(value)),

            $parent = $field.parent();

        $parent.find("input.coral-Textfield").val(date.format($parent.data("displayed-format")));

        $field.val(date.format($parent.data("stored-format")));

    }

    function isTagsField($fieldWrapper) {

        return !_.isEmpty($fieldWrapper) && ($fieldWrapper.children(".js-cq-TagsPickerField").length > 0);

    }

    function getTagsFieldName($fieldWrapper) {

        return $fieldWrapper.children(".js-cq-TagsPickerField").data("property-path").substr(2);

    }

    function getTagObject(tag){

        var tagPath = "/etc/tags/" + tag.replace(":", "/");

        return $.get(tagPath + ".tag.json");

    }

    function setTagsField($fieldWrapper, tags) {

        if(_.isEmpty(tags)){

            return;

        }

        var cuiTagList = $fieldWrapper.find(".coral-TagList").data("tagList");

        _.each(tags, function(tag){

            getTagObject(tag).done(function(data){

                cuiTagList._appendItem( { value: data.tagID, display: data.titlePath} );

            });

        });

    }

    function isMultifield($formFieldWrapper){

        return ($formFieldWrapper.children("[data-init='multifield']").length > 0);

    }

    function setWidgetValue($field, value) {

        if (_.isEmpty($field)) {

            return;

        }

        if(isSelectOne($field)) {

            setSelectOne($field, value);

        }else if(isCheckbox($field)) {

            setCheckBox($field, value);

        }else if(isDateField($field)) {

            setDateField($field, value);

        }else {

            $field.val(value);

        }

    }

    function getMultifields($formField, isInner){

        var mNames = {}, mName, $multifield, $template,

            $multiTemplates = $formField.find(".js-coral-Multifield-input-template");

        $multiTemplates.each(function (i, template) {

            $template = $(template);

            $multifield = $($template.html());

            if(!isInner && !isNodeStoreMultifield($multifield.data(EAEM_NESTED))){

                return;

            }

            mName = $multifield.data("name").substring(2);

            mNames[mName] = $template.closest(".coral-Multifield");

        });

        return mNames;

    }

    function buildMultifield(data, $multifield, mName){

        var $formFieldWrapper, $field, $fieldSet, name,

            innerMultifields;

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

            if(key.indexOf("jcr:") === 0){

                return;

            }

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

            $fieldSet = $multifield.find(".coral-Form-fieldset").last();

            _.each($fieldSet.find(CFFW), function (formFieldWrapper) {

                $formFieldWrapper = $(formFieldWrapper);

                if(isMultifield($formFieldWrapper)){

                    innerMultifields = getMultifields($formFieldWrapper, true);

                    _.each(innerMultifields, function($innerMultifield, nName){

                        buildMultifield(value[nName], $innerMultifield, nName);

                    });

                    return;

                }else if(isTagsField($formFieldWrapper)){

                    setTagsField($formFieldWrapper, value[getTagsFieldName($formFieldWrapper)]);

                    return;

                }

                $field = $formFieldWrapper.find("[name]");

                if(_.isEmpty($field)){

                    return;

                }

                name = $field.attr("name").substr(2);

                if(_.isEmpty(value[name])){

                    return;

                }

                setWidgetValue($field, value[name]);

            });

        })

    }

    function addDataInFields() {

        $document.on("dialog-ready", dlgReadyHandler);

        function dlgReadyHandler() {

            var outerMultifields = getMultifields($(this), false),

                $form = $("form.cq-dialog"),

                actionUrl = $form.attr("action") + ".infinity.json";

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

            function postProcess(data){

                _.each(outerMultifields, function($outerMultifield, mName){

                    buildMultifield(data[mName], $outerMultifield, mName);

                    if($('.coral-Multifield-list.js-coral-Multifield-list li').length === 0)

                    $(".js-coral-Multifield-add").trigger('click');

                });

            }

        }

    }

    function fillValue($form, fieldSetName, $field, counter){

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

        if (!name) {

            return;

        }

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

            name = name.substring(2);

        }

        value = $field.val();

        if (isCheckbox($field)) {

            value = $field.prop("checked") ? $field.val() : "";

        }

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

        $field.remove();

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

            .attr('name', fieldSetName + "/" + counter + "/" + name)

            .attr('value', value)

            .appendTo($form);

    }

    function addNestedMultifieldData($form, outerMultiName, $nestedMultiField){

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

            nName = $fieldSets.data("name"), $fields;

        if(!nName){

            return;

        }

        nName = outerMultiName + "/" + nName.substring(2);

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

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

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

                fillValue($form, nName, $(field), (iCounter + 1));

            });

        });

    }

    function collectDataFromFields(){

        $document.on("click", ".cq-dialog-submit", collectHandler);

        function collectHandler() {

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

                mName = $("[" + DATA_EAEM_NESTED + "]").data("name"),

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

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

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

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

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

                    $field = $(field);

                    //may be a nested multifield

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

                    if($nestedMultiField.length == 0){

                        fillValue($form, mName, $(field).find("[name]"), (oCounter + 1));

                    }else{

                        addNestedMultifieldData($form, mName + "/" + (oCounter + 1) , $nestedMultiField);

                    }

                });

            });

        }

    }

    $document.ready(function () {

        addDataInFields();

        collectDataFromFields();

    });

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

    //for working around the nested multifield add and reorder

    CUI.Multifield = new Class({

        toString: "Multifield",

        extend: CUI.Multifield,

        construct: function () {

            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.Multifield);

})(jQuery, jQuery(document));

We hope this information helps!

Regards,

TechAspect Solutions

View solution in original post

3 Replies

Avatar

Correct answer by
Level 7

Hi,

Assuming that you're using sling:resourceType as "granite/ui/components/foundation/form/fieldset", please use the following JS logic (nested-multifield.js here) that creates and fills the nested multifield with one multifield item open by default on dialog load. The highlighted lines of code in the below js file is responsible for populating one multifield item open by default if there is no data available.

nested-multifield.js:

(function ($, $document) {

    var EAEM_NESTED = "eaem-nested",

        DATA_EAEM_NESTED = "data-" + EAEM_NESTED,

        CFFW = ".coral-Form-fieldwrapper",

        NODE_STORE = "NODE_STORE";

    if(CUI.Multifield.eaemNMFExtended){

        return;

    }

    CUI.Multifield.eaemNMFExtended = true;

    function isNodeStoreMultifield(type) {

        return (type === NODE_STORE);

    }

    function isSelectOne($field) {

        return !_.isEmpty($field) && ($field.prop("type") === "select-one");

    }

    function setSelectOne($field, value) {

        var select = $field.closest(".coral-Select").data("select");

        if (select) {

            select.setValue(value);

        }

    }

    function isCheckbox($field) {

        return !_.isEmpty($field) && ($field.prop("type") === "checkbox");

    }

    function setCheckBox($field, value) {

        $field.prop("checked", $field.attr("value") === value);

    }

    function isDateField($field) {

        return !_.isEmpty($field) && $field.parent().hasClass("coral-DatePicker");

    }

    function setDateField($field, value) {

        var date = moment(new Date(value)),

            $parent = $field.parent();

        $parent.find("input.coral-Textfield").val(date.format($parent.data("displayed-format")));

        $field.val(date.format($parent.data("stored-format")));

    }

    function isTagsField($fieldWrapper) {

        return !_.isEmpty($fieldWrapper) && ($fieldWrapper.children(".js-cq-TagsPickerField").length > 0);

    }

    function getTagsFieldName($fieldWrapper) {

        return $fieldWrapper.children(".js-cq-TagsPickerField").data("property-path").substr(2);

    }

    function getTagObject(tag){

        var tagPath = "/etc/tags/" + tag.replace(":", "/");

        return $.get(tagPath + ".tag.json");

    }

    function setTagsField($fieldWrapper, tags) {

        if(_.isEmpty(tags)){

            return;

        }

        var cuiTagList = $fieldWrapper.find(".coral-TagList").data("tagList");

        _.each(tags, function(tag){

            getTagObject(tag).done(function(data){

                cuiTagList._appendItem( { value: data.tagID, display: data.titlePath} );

            });

        });

    }

    function isMultifield($formFieldWrapper){

        return ($formFieldWrapper.children("[data-init='multifield']").length > 0);

    }

    function setWidgetValue($field, value) {

        if (_.isEmpty($field)) {

            return;

        }

        if(isSelectOne($field)) {

            setSelectOne($field, value);

        }else if(isCheckbox($field)) {

            setCheckBox($field, value);

        }else if(isDateField($field)) {

            setDateField($field, value);

        }else {

            $field.val(value);

        }

    }

    function getMultifields($formField, isInner){

        var mNames = {}, mName, $multifield, $template,

            $multiTemplates = $formField.find(".js-coral-Multifield-input-template");

        $multiTemplates.each(function (i, template) {

            $template = $(template);

            $multifield = $($template.html());

            if(!isInner && !isNodeStoreMultifield($multifield.data(EAEM_NESTED))){

                return;

            }

            mName = $multifield.data("name").substring(2);

            mNames[mName] = $template.closest(".coral-Multifield");

        });

        return mNames;

    }

    function buildMultifield(data, $multifield, mName){

        var $formFieldWrapper, $field, $fieldSet, name,

            innerMultifields;

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

            if(key.indexOf("jcr:") === 0){

                return;

            }

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

            $fieldSet = $multifield.find(".coral-Form-fieldset").last();

            _.each($fieldSet.find(CFFW), function (formFieldWrapper) {

                $formFieldWrapper = $(formFieldWrapper);

                if(isMultifield($formFieldWrapper)){

                    innerMultifields = getMultifields($formFieldWrapper, true);

                    _.each(innerMultifields, function($innerMultifield, nName){

                        buildMultifield(value[nName], $innerMultifield, nName);

                    });

                    return;

                }else if(isTagsField($formFieldWrapper)){

                    setTagsField($formFieldWrapper, value[getTagsFieldName($formFieldWrapper)]);

                    return;

                }

                $field = $formFieldWrapper.find("[name]");

                if(_.isEmpty($field)){

                    return;

                }

                name = $field.attr("name").substr(2);

                if(_.isEmpty(value[name])){

                    return;

                }

                setWidgetValue($field, value[name]);

            });

        })

    }

    function addDataInFields() {

        $document.on("dialog-ready", dlgReadyHandler);

        function dlgReadyHandler() {

            var outerMultifields = getMultifields($(this), false),

                $form = $("form.cq-dialog"),

                actionUrl = $form.attr("action") + ".infinity.json";

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

            function postProcess(data){

                _.each(outerMultifields, function($outerMultifield, mName){

                    buildMultifield(data[mName], $outerMultifield, mName);

                    if($('.coral-Multifield-list.js-coral-Multifield-list li').length === 0)

                    $(".js-coral-Multifield-add").trigger('click');

                });

            }

        }

    }

    function fillValue($form, fieldSetName, $field, counter){

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

        if (!name) {

            return;

        }

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

            name = name.substring(2);

        }

        value = $field.val();

        if (isCheckbox($field)) {

            value = $field.prop("checked") ? $field.val() : "";

        }

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

        $field.remove();

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

            .attr('name', fieldSetName + "/" + counter + "/" + name)

            .attr('value', value)

            .appendTo($form);

    }

    function addNestedMultifieldData($form, outerMultiName, $nestedMultiField){

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

            nName = $fieldSets.data("name"), $fields;

        if(!nName){

            return;

        }

        nName = outerMultiName + "/" + nName.substring(2);

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

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

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

                fillValue($form, nName, $(field), (iCounter + 1));

            });

        });

    }

    function collectDataFromFields(){

        $document.on("click", ".cq-dialog-submit", collectHandler);

        function collectHandler() {

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

                mName = $("[" + DATA_EAEM_NESTED + "]").data("name"),

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

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

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

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

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

                    $field = $(field);

                    //may be a nested multifield

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

                    if($nestedMultiField.length == 0){

                        fillValue($form, mName, $(field).find("[name]"), (oCounter + 1));

                    }else{

                        addNestedMultifieldData($form, mName + "/" + (oCounter + 1) , $nestedMultiField);

                    }

                });

            });

        }

    }

    $document.ready(function () {

        addDataInFields();

        collectDataFromFields();

    });

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

    //for working around the nested multifield add and reorder

    CUI.Multifield = new Class({

        toString: "Multifield",

        extend: CUI.Multifield,

        construct: function () {

            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.Multifield);

})(jQuery, jQuery(document));

We hope this information helps!

Regards,

TechAspect Solutions

Avatar

Level 4

Hi,

Thanks a lot for your reply but i just want a validation where i can check if I have any mulitfield already in the dialog then do nothing and if the dialof don't have any multifield data, then show one multifield, so that author understands what data to fill in the box and disable delete button in case there is only one multifield available in the dialog box.

Any solution around this?

Avatar

Community Advisor

This is not something which is possible with OOTB multiifled. You may have to do a workaround by customizing it .