Expand my Community achievements bar.

July 31st AEM Gems Webinar: Elevate your AEM development to master the integration of private GitHub repositories within AEM Cloud Manager.
SOLVED

Writing Sling Models for Nested Multifields.

Avatar

Level 3

How can I write a sling Model to display a nested multifield with an image field in one of the multifield?

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

You can refer https://blogs.perficient.com/2018/08/24/using-sling-models-with-nested-composite-mulitifields-in-aem... , I used the similar approach to manage pathbrowser (to select image) , text area( for description) and text field(title).

View solution in original post

4 Replies

Avatar

Correct answer by
Employee Advisor

You can refer https://blogs.perficient.com/2018/08/24/using-sling-models-with-nested-composite-mulitifields-in-aem... , I used the similar approach to manage pathbrowser (to select image) , text area( for description) and text field(title).

Avatar

Employee Advisor

Sample code for nested multifields- 

 

1. Sling model -

     

package com.aem.demo.core.models;

import java.util.List;
import javax.inject.Inject;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;

@Model(
	    adaptables = {Resource.class},
	    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public interface CompaniesModel {
	@Inject
	  List<Company> getCompanies(); // the name `getCompanies` corresponds to the multifield name="./companies"
	  /**
	   * Company model
	   * has a name and a list of departments
	   */
	  @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
	  interface Company {
	    @Inject
	    String getName();
	    @Inject
	    List<Department> getDepartments(); // the name `getDepartments` corresponds to the multifield name="./departments"
	  }
	  /**
	   * Department model
	   * has a name and a manager
	   */
	  @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
	  interface Department {
	    @Inject
	    String getImage();
	    
	  }

}

 

2. .context.xml associated with 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="Companies"
    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">
                    <companies
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                        composite="{Boolean}true"
                        fieldDescription="Click 'Add Field' to add a new company.">
                        <field
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/container"
                            name="./companies">
                            <items jcr:primaryType="nt:unstructured">
                                <name
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                    fieldLabel="Comp. Name"
                                    name="name"/>
                                <departments
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                    composite="{Boolean}true"
                                    fieldDescription="Click 'Add Field' to add a new department."
                                    fieldLabel="Departments">
                                    <field
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/container"
                                        name="./departments">
                                        <items jcr:primaryType="nt:unstructured">
                                            <image
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
                                                fieldLabel="Image"
                                                name="image"
                                                rootPath="/content/dam/we-retail/en/people"/>
                                        </items>
                                    </field>
                                </departments>
                            </items>
                        </field>
                    </companies>
                </items>
            </column>
        </items>
    </content>
</jcr:root>

 

3. htl code -

<sly data-sly-use.companiesModel="com.aem.demo.core.models.CompaniesModel"/>
<sly data-sly-test.empty="${!companiesModel.companies}" />
<div data-sly-test="${wcmmode.edit && empty}" class="cq-placeholder" data-emptytext="${component.title}"></div>
<sly data-sly-test="${!empty}">
  <div>
      <ul data-sly-list.company="${companiesModel.companies}">
        <li>${company.name}
          <ul data-sly-list.department="${company.departments}">
            <li>
               <img src="${department.image}" width="300" height="300"></br>
            </li>
          </ul>
        </li>
      </ul>
  </div>
</sly>

4.  Author's entries using touch ui dialog and rendered output -

DEBAL_DAS_0-1650791505603.pngDEBAL_DAS_1-1650791514359.pngDEBAL_DAS_2-1650791532184.png

DEBAL_DAS_3-1650791541797.png

 

Avatar

Community Advisor

Dear @Manasi29 

 

You can use list of class as mentioned below for filed injectors

@Model(adaptables = {Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public interface CompaniesModel {
  @Inject
  List<Names> getNames(); // `getNames` corresponds to the multifield name="./names"
  /**
   * Names model
   * has a name and a list of first names
   */
  @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
  interface Names {
    @Inject
    String getFirstName();
  }
  /**
   * First Name model
   * 
   */
  @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
  interface Firstname {
    @Inject
    String getName();
  }
}

Regards,

Santosh