Tuesday 25 February 2020

AEM Dialog | Multifield

Steps to create multi-field and use it.

Step 1) Creating one multifield in diaog, where each field contains title and pageno. field.
Add below code in dialog items.
Note: Used multifield inside accordion, so that author can also expand and collapse multifield.


                                         <accordion

                                                granite:class="js-cq-IPEPlugin-container"
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/accordion"
                                                variant="default">
                                                <items jcr:primaryType="nt:unstructured">
                                                    <multifield
                                                        jcr:primaryType="nt:unstructured"
                                                        jcr:title="My Composite Multifield"
                                                        sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                                        composite="{Boolean}true">
                                                        <field
                                                            jcr:primaryType="nt:unstructured"
                                                            sling:resourceType="granite/ui/components/coral/foundation/container"
                                                            name="./mymultifield">
                                                            <items jcr:primaryType="nt:unstructured">
                                                                <title
                                                                    jcr:primaryType="nt:unstructured"
                                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                                    fieldLabel="Title"
                                                                    name="title"
                                                                    required="true"/>
                                                                <pageno
                                                                    jcr:primaryType="nt:unstructured"
                                                                    sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
                                                                    defaultValue="3"
                                                                    fieldLabel="Page Number"
                                                                    max="12"
                                                                    min="1"
                                                                    name="pageno"
                                                                    required="true"/>
                                                            </items>
                                                        </field>
                                                    </multifield>
                                                </items>
                                            </accordion>




                   This will look like as shown below:

This will store content in below node structure form:




Step 2) Now include below two model files in your bundle.

1) MultifieldModel.java 

package pom.core.models;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import com.day.cq.wcm.api.Page;

@Model(adaptables = SlingHttpServletRequest.class,
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MultifieldModel {

  @SlingObject
  private ResourceResolver resourceResolver;

  @ScriptVariable
  private Page currentPage;

  @ScriptVariable
  private Node currentNode;

  @Inject
  public List<Resource> mymultifield;

  public List<MultifieldSectionModel> multifieldList;

  @PostConstruct
  private void init() throws RepositoryException {
    if (null == resourceResolver || null == currentPage) {
      return;
    }
    final Resource currentresource = resourceResolver.resolve(currentNode.getPath());
    if (null == mymultifield
        && null != currentresource.getChild("mymultifield")) {
      mymultifield = new ArrayList<>();
      final Resource mymultifieldResource =
          currentresource.getChild("mymultifield");
      if (null == mymultifieldResource) {
        return;
      }
      final Iterable<Resource> iterable = mymultifieldResource.getChildren();
      final Iterator<Resource> itr = iterable.iterator();
      while (itr.hasNext()) {
        mymultifield.add(itr.next());
      }
    }
  }

  public List<MultifieldSectionModel> getMultifieldList() {
    if (null == multifieldList) {
      multifieldList = new ArrayList<>();
    }
    for (final Resource res : mymultifield) {
      multifieldList.add(res.adaptTo(MultifieldSectionModel.class));
    }
    return multifieldList;
  }

  public List<Resource> getMymultifield() {
    return mymultifield;
  }
}

2) MultifieldSectionModel.java

package pom.core.models;

import javax.inject.Inject;
import javax.inject.Named;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;

@Model(adaptables = {Resource.class})
public class MultifieldSectionModel {

  @Inject
  @Named("title")
  @Optional
  private String title;

  @Inject
  @Named("pageno")
  @Optional
  private String pageno;

  public String getTitle() {
    return title;
  }

  public void setTitle(final String title) {
    this.title = title;
  }

  public String getPageno() {
    return pageno;
  }

  public void setPageno(final String pageno) {
    this.pageno = pageno;
  }
}


Step 3) Now use below sightly code to display it in site

Below is the list:
<sly data-sly-use.multifieldModel="pom.core.models.MultifieldModel">
<ul data-sly-list="${multifieldModel.multifieldList}">
<li id="${itemList.count}">${item.title} ...... ${item.pageno}</li>
</ul>



 This will display as below in UI


Note:
When we have requirement just to have single item in multifield, then we can implement like shown below, it will not create multiple nodes but it will store it as String[] property in component node itself.

<youtubeurl
jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/foundation/form/multifield"
    fieldLabel="Youtube URL">
    <field
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
        name="./youtubeurl"
        required="{Boolean}true"/>
</youtubeurl>

No comments:

Post a Comment