Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

How do we store multifields with more than one field as array in AEM 6.5?

Avatar

Level 4

How do we store multifield that has more than one field as array in AEM 6.5 as acs-commons-nested property is deprecated in 6.5?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @chinmayis865517 

If you have a component that uses both Classic UI and Touch UI dialogs, and you want to ensure that the multifield data is synchronized between the two dialogs, you will need to implement some custom logic.

Here's an approach you can take to handle this scenario:

1. In your Classic UI dialog, add a hidden field to store the multifield data as JSON.

<mycomponent
    jcr:primaryType="cq:Widget"
    xtype="dialog">
    
    <items jcr:primaryType="cq:WidgetCollection">
        <!-- Other fields -->
        
        <myMultifieldData
            jcr:primaryType="cq:Widget"
            xtype="hidden"
            name="./myMultifieldData"/>
    </items>
</mycomponent>

2. In your Classic UI JSP, retrieve the multifield data from the hidden field and convert it to a JSON object.

<%
String multifieldData = properties.get("myMultifieldData", "");
JSONArray jsonArray = new JSONArray(multifieldData);
%>


3. Iterate over the JSON array and render the multifield data in your Classic UI JSP.

<%
for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject jsonObject = jsonArray.getJSONObject(i);
    String field1Value = jsonObject.getString("field1");
    String field2Value = jsonObject.getString("field2");
    
    // Render the fields as needed
}
%>

4. In your Touch UI dialog, use the Coral 3 multifield component as described in the previous answer.

5. In your Touch UI dialog's client-side JS, populate the Classic UI hidden field with the multifield data.

(function($, $document) {
    "use strict";

    $document.on("dialog-ready", function() {
        var $multifield = $("coral-multifield[name='./myMultifield']");

        $multifield.on("change", function() {
            var multifieldData = [];

            $multifield.find("coral-multifield-item").each(function() {
                var $item = $(this);
                var field1Value = $item.find("coral-autocomplete[name='./field1']").val();
                var field2Value = $item.find("coral-textfield[name='./field2']").val();

                multifieldData.push({
                    field1: field1Value,
                    field2: field2Value
                });
            });

            // Store the multifield data in the Classic UI hidden field
            $("input[name='./myMultifieldData']").val(JSON.stringify(multifieldData));
        });
    });
})(jQuery, jQuery(document));

By populating the Classic UI hidden field with the multifield data from the Touch UI dialog, you ensure that the data is synchronized between the two dialogs. This way, when the data is submitted from the Classic UI dialog, it will be rendered correctly.



View solution in original post

6 Replies

Avatar

Community Advisor

Hi @chinmayis865517 ,


In AEM 6.5, the ACS Commons Nested Property approach for storing multifield data as an array is indeed deprecated. Instead, you can use Coral 3 Multifield for handling multifield data. Here's how you can implement it:

  1. Within your component's dialog, incorporate a Multifield interface to enable authors to include multiple field sets
  2. Each set within the Multifield corresponds to a single item in the array.
  3. Customize the fields within the Multifield, specifying their names and types as required.
  4. When the author submits the dialog, the data from the multifield will be sent as an array of objects. You can access this data in your servlet or model class and process it accordingly.
  5. When rendering the component on the page, iterate over the array of objects and display the data as needed.
<myMultifield
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
    fieldLabel="My Multifield"
    name="./myMultifield">
    <items jcr:primaryType="nt:unstructured">
        <field
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
            fieldLabel="Field 1"
            name="./field1"/>
        <field
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
            fieldLabel="Field 2"
            name="./field2"/>
        <!-- Add more fields as needed -->
    </items>
</myMultifield>

In your servlet or model class, you would then handle the multifield data as an array of objects and process it accordingly.

Thanks,
Madhur

Avatar

Level 4

Hi @Madhur-Madan ,

 

Thank you for your response.

The same component also uses classic dialog and the multifield gets stores as json here which is not in sync with touch ui dialog. In the existing JSP I have written the logic to retrieve the nodes created from touch ui, but when the data are submitted from classic ui dialog , they will not be rendered.

 

 

Avatar

Correct answer by
Community Advisor

Hi @chinmayis865517 

If you have a component that uses both Classic UI and Touch UI dialogs, and you want to ensure that the multifield data is synchronized between the two dialogs, you will need to implement some custom logic.

Here's an approach you can take to handle this scenario:

1. In your Classic UI dialog, add a hidden field to store the multifield data as JSON.

<mycomponent
    jcr:primaryType="cq:Widget"
    xtype="dialog">
    
    <items jcr:primaryType="cq:WidgetCollection">
        <!-- Other fields -->
        
        <myMultifieldData
            jcr:primaryType="cq:Widget"
            xtype="hidden"
            name="./myMultifieldData"/>
    </items>
</mycomponent>

2. In your Classic UI JSP, retrieve the multifield data from the hidden field and convert it to a JSON object.

<%
String multifieldData = properties.get("myMultifieldData", "");
JSONArray jsonArray = new JSONArray(multifieldData);
%>


3. Iterate over the JSON array and render the multifield data in your Classic UI JSP.

<%
for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject jsonObject = jsonArray.getJSONObject(i);
    String field1Value = jsonObject.getString("field1");
    String field2Value = jsonObject.getString("field2");
    
    // Render the fields as needed
}
%>

4. In your Touch UI dialog, use the Coral 3 multifield component as described in the previous answer.

5. In your Touch UI dialog's client-side JS, populate the Classic UI hidden field with the multifield data.

(function($, $document) {
    "use strict";

    $document.on("dialog-ready", function() {
        var $multifield = $("coral-multifield[name='./myMultifield']");

        $multifield.on("change", function() {
            var multifieldData = [];

            $multifield.find("coral-multifield-item").each(function() {
                var $item = $(this);
                var field1Value = $item.find("coral-autocomplete[name='./field1']").val();
                var field2Value = $item.find("coral-textfield[name='./field2']").val();

                multifieldData.push({
                    field1: field1Value,
                    field2: field2Value
                });
            });

            // Store the multifield data in the Classic UI hidden field
            $("input[name='./myMultifieldData']").val(JSON.stringify(multifieldData));
        });
    });
})(jQuery, jQuery(document));

By populating the Classic UI hidden field with the multifield data from the Touch UI dialog, you ensure that the data is synchronized between the two dialogs. This way, when the data is submitted from the Classic UI dialog, it will be rendered correctly.



Avatar

Community Advisor

@chinmayis865517 , Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.

Avatar

Level 4

I'm rendering the content from the touch ui and pointing the classic dialog to touch , in case the author tries to open it from the classic ui.

Avatar

Administrator

@chinmayis865517 Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni