Multifield Component in AEM 6.X

In Previous, Post we saw the how to create Component in aem using sling model. Today we will see how to create multifield component in aem.



The OOB Multifield component came with many limitations. So we should not use that approach, since it does not allow us to do much enhancement. But due to ACS we can do that. ACS common (Adobe consulting services) an open source community for enhancing the existing granite multifield component.

(granite/ui/components/foundation/form/multifield)

Which allows to create a multifield of a field-set we can have multiple different different fields.

Here we are developing the Multifield component for Touch-UI by using HTL in (Adobe Experience Manager) AEM 6.5

Multifield enables us to add number of files in the dialog as per requirement so we can add as many as we want. We have Sling model to map those values basically for one-time fields you can assume it as Pojo and we also have another Sling model where we will fetch the number of fields as list.

Here we are going to create Product multifield with Product and email text fields-

Here is the Component dialog xml



<?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=“test Multifield”
  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”
                        eaem-show-on-collapse=“EAEM.showProductName”
                        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”/>

                                        <email

                                            jcr:primaryType=“nt:unstructured” sling:resourceType=“granite/ui/components/coral/foundation/form/textfield”
                                           fieldLabel=“Email”
                                           name=“./email”/>
                                           </items>
                                         </column>
                                        </items>
                                      </field>
                                    </products>
                                  </items>
                             </column>
                       </items>
                    </content>
                </jcr:root>

 

Here is the Product Sling model class



package com.aemtrainingsite.core.models;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;

@Model(adaptables = Resource.class)
public class Product {
private final Logger logger = LoggerFactory.getLogger(getClass());

@ValueMapValue
private String product;

@ValueMapValue
private String email;

@PostConstruct
protected void init() {

logger.info(“In init of State2 Model”);}

public String getProduct() {

return product;}

public String getEmail() {

return email;}}

Here is the Test Model class since we need one extra class for Multifield to call the POJO class.

 



 

package com.aemtrainingsite.core.models;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Model(adaptables = Resource.class)
public class TestModel {

              private final Logger logger = LoggerFactory.getLogger(getClass());
              @Inject
              @Named(“sling:resourceType”)
              @Default(values = “No resourceType”)
              protected String resourceType;

              @Inject
              @Optional
              private List<Resource> products;

              private List<Product> productsList = new ArrayList<>();

              public List<Product> getProductsList() {

                             return productsList;}

              public void setProductsList(List<Product> productsList) {

                             this.productsList = productsList;}

                     @PostConstruct

              protected void init() {

                             logger.info(“—-<In init of Test Model >—–“);

                             if (!products.isEmpty()) {

                                           for (Resource resource : products) {

                                                          Product p1 = resource.adaptTo(Product.class);

                                                          productsList.add(p1);}}}}

Here is the HTL



<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}"/>
 <sly data-sly-call=“${clientLib.all @ categories=’validation.file’}”/>
<div>
 <b>Product Details</b>
<div data-sly-use.testModel=“com.pstrainingsite.core.models.TestModel” data-sly-unwrap>
<div data-sly-test=“${!testModel || wcmmode.edit}”>
  Add state details using component dialog
      </div>
    <div data-sly-test=“${testModel.productsList}”>
            <div data-sly-list.products=“${testModel.productsList}”>
                <div>
                    <div>Name: ${products.product}</div>
                        <div>Email: ${products.email}</div>
                    <br>                   
                    </div>
                   </div>
                  </div>
                </div>
               </div>

Build and Deploy your code.

mvn clean install -PautoInstallPackage



If you really find this post useful, you can help me to keep this alive by buying me a cup of Coffee.

Stay Safe & Healthy                                              Happy Learning & Coding