AEM 64 - Touch UI Nested Composite Multifield Using Coral 3

Goal


Create a sample component dialog using nested composite coral 3 multifield/libs/granite/ui/components/coral/foundation/form/multifield

Demo | Package Install | Github


Multifield Structure in CRX



Multifield in Dialog



Multifield Storage in CRX



Component Rendering



Solution


1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-coral3-nested-composite-multifield

2) Sample dialog with nested composite multifield /apps/eaem-coral3-nested-composite-multifield/sample-nested-composite-multifield/cq: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="64 Nested Composite Multi Field"
    sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
        <items jcr:primaryType="nt:unstructured">
            <column
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/container">
                <items jcr:primaryType="nt:unstructured">
                    <products
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                        composite="{Boolean}true"
                        fieldLabel="Products">
                        <field
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/container"
                            name="./products">
                            <items jcr:primaryType="nt:unstructured">
                                <column
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/container">
                                    <items jcr:primaryType="nt:unstructured">
                                        <product
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                            fieldDescription="Name of Product"
                                            fieldLabel="Product Name"
                                            name="./product"/>
                                        <components
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                            composite="{Boolean}true"
                                            fieldLabel="Components">
                                            <field
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                                name="./components">
                                                <items jcr:primaryType="nt:unstructured">
                                                    <column
                                                        jcr:primaryType="nt:unstructured"
                                                        sling:resourceType="granite/ui/components/coral/foundation/container">
                                                        <items jcr:primaryType="nt:unstructured">
                                                            <component
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                                fieldDescription="Name of Component"
                                                                fieldLabel="Component Name"
                                                                name="./component"/>
                                                            <compPath
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/form/pathbrowser"
                                                                fieldDescription="Select Path"
                                                                fieldLabel="Path"
                                                                name="./compPath"
                                                                rootPath="/content"/>
                                                            <size
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                                                fieldDescription="Select Size"
                                                                fieldLabel="Size"
                                                                name="./size">
                                                                <items jcr:primaryType="nt:unstructured">
                                                                    <def
                                                                        jcr:primaryType="nt:unstructured"
                                                                        text="Select Size"
                                                                        value=""/>
                                                                    <small
                                                                        jcr:primaryType="nt:unstructured"
                                                                        text="Small"
                                                                        value="small"/>
                                                                    <medium
                                                                        jcr:primaryType="nt:unstructured"
                                                                        text="Medium"
                                                                        value="medium"/>
                                                                    <large
                                                                        jcr:primaryType="nt:unstructured"
                                                                        text="Large"
                                                                        value="large"/>
                                                                </items>
                                                            </size>
                                                        </items>
                                                    </column>
                                                </items>
                                            </field>
                                        </components>
                                    </items>
                                </column>
                            </items>
                        </field>
                    </products>
                </items>
            </column>
        </items>
    </content>
</jcr:root>


3) #17 composite=true is for outer composite multifield (./products) and #37 composite=true for inner composite multifield (./components)

4) Create file (nt:file) /apps/eaem-coral3-nested-composite-multifield/sample-nested-composite-multifield/helper.js, add the following code for reading stored nodes

"use strict";

use( ["/libs/wcm/foundation/components/utils/ResourceUtils.js","/libs/sightly/js/3rd-party/q.js" ], function(ResourceUtils, Q){
    log.info("Rendering....");

    var prodPromise = Q.defer(), company = {},
        productsPath = granite.resource.path + "/products";

    company.products = undefined;

    ResourceUtils.getResource(productsPath)
            .then(function (prodParent) {
                return prodParent.getChildren();
            })
            .then(function(products) {
                addProduct(products, 0);
            });

    function addProduct(products, currIndex){
        if(!company.products){
            company.products = [];
        }

        if (currIndex >= products.length) {
            prodPromise.resolve(company);
            return;
        }

        var productRes = products[currIndex],
            properties = productRes.properties;

        var product = {
            path: productRes.path,
            name: properties["product"]
        };

        ResourceUtils.getResource(productRes.path + "/components")
            .then(function (compParent) {
                return compParent.getChildren();
            })
            .then(function(components) {
                addComponent(product, components, 0);
            });

        company.products.push(product);

        addProduct(products, (currIndex + 1));
    }

    function addComponent(product, components, currIndex){
        if(!product.components){
            product.components = [];
        }

        if (currIndex >= components.length) {
            return;
        }

        var compRes = components[currIndex],
            properties = compRes.properties;

        var component = {
            path: compRes.path,
            name: properties.component,
            compPath: properties.compPath,
            size: properties.size
        };

        product.components.push(component);

        addComponent(product, components, (currIndex + 1));
    }

    return prodPromise.promise;
} );


5) Create file (nt:file) /apps/eaem-coral3-nested-composite-multifield/sample-nested-composite-multifield/sample-nested-composite-multifield.html, add the following code for rendering data

<div>
    <b>64 Nested Composite Multifield</b>

    <div data-sly-use.company="helper.js" data-sly-unwrap>
        <div data-sly-test="${!company.products && wcmmode.edit}">
            Add products using component dialog
        </div>

        <div data-sly-test="${company.products}">
            <div data-sly-list.product="${company.products}">
                <div>
                    <div>${product.name}</div>

                    <div data-sly-list.component="${product.components}" style="margin-left:40px">
                        <div><b>${component.name}</b></div>
                        <div>${component.compPath}</div>
                        <div>${component.size}</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>




5 comments:

  1. could you please share sightly version for the same nested multifield

    ReplyDelete
  2. Thanks for sharing the post, After creating the dialog and opening it again, it behaves slightly different and does not render the correct heirarchy when click on Add. Do you know the reason for it. I am using AEM6.3 with above dialog (Coral 3)

    ReplyDelete
  3. having same issue, when click on outer Add-filed button, only inner multi-field showing up without the outer multi-field.
    AEM6.3 and coral-3

    ReplyDelete
  4. We have migrated to AEM 6.5.
    We are facing an issue while opening a Touch UI dialog with multifield developed as in this blog. The already authored fields are not rendering in dialog and also we are not able to edit the multifield

    Below is the error we are getting in console

    Uncaught RangeError: Maximum call stack size exceeded composite-multifield.min.js:14

    We have latest ACS commons installed. Please suggest us to overcome this.

    ReplyDelete