Expand my Community achievements bar.

Radically easy to access on brand approved content for distribution and omnichannel performant delivery. AEM Assets Content Hub and Dynamic Media with OpenAPI capabilities is now GA.
SOLVED

Simplest way to implement Multifield in Sling Models

Avatar

Level 5

Hi all,

I want to write a sling models for multifield for touch ui component. If any one having idea to write the sling model for multifield with minimal code please suggest some examples.

Thanks

1 Accepted Solution

Avatar

Correct answer by
Level 3
public List<String> getCqTags() {
    List<String> parentTags = new ArrayList<>();
    Page currentPage = pageManager.getContainingPage(getResource());
    ValueMap props = currentPage.getProperties();
    String[] cqTags = props.get("cq:tags", String[].class);
    for (String tag : cqTags) {
        //check if the tag has child tags or not
        if (!hasChildTags(tag)) {
            //if the tag is leaf node, add its parent tag
            parentTags.add(getParentTag(tag));
        }
    }
    logger.info("Parent cq:tags property of leaf tags: {}", parentTags);
    return parentTags;
}

View solution in original post

7 Replies

Avatar

Community Advisor

Hi @Nandheswara 

 

Please find my blog here which explains all the steps to create a MF: https://allaembykiran.wordpress.com/2021/01/13/nested-multi-field/

 

Hope this helps!


Thanks,
Kiran Vedantam.

Avatar

Level 3
public List<String> getCqTags() {
    List<String> level2Tags = new ArrayList<>();
    Page currentPage = pageManager.getContainingPage(getResource());
    ValueMap props = currentPage.getProperties();
    String[] cqTags = props.get("cq:tags", String[].class);
    for (String tag : cqTags) {
        if(tag.split("/").length == 2) {
            level2Tags.add(tag);
        }
    }
    logger.info("Level 2 cq:tags property: {}", level2Tags);
    return level2Tags;
}




Avatar

Correct answer by
Level 3
public List<String> getCqTags() {
    List<String> parentTags = new ArrayList<>();
    Page currentPage = pageManager.getContainingPage(getResource());
    ValueMap props = currentPage.getProperties();
    String[] cqTags = props.get("cq:tags", String[].class);
    for (String tag : cqTags) {
        //check if the tag has child tags or not
        if (!hasChildTags(tag)) {
            //if the tag is leaf node, add its parent tag
            parentTags.add(getParentTag(tag));
        }
    }
    logger.info("Parent cq:tags property of leaf tags: {}", parentTags);
    return parentTags;
}

Avatar

Community Advisor

Hi @Nandheswara , It all depend on complexity on your use case/Multifield. I am sharing a pseudo code having 3 fields in multifield  and in sling model it handling using MAP. Update field names as per need. I will also add links to complete files

Dialog(only multifield pseudo code. Will leave link to complete dialog file)

                                    <bookdetailswithmap
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                        composite="{Boolean}true"
                                        fieldDescription="Books Details"
                                        fieldLabel="Book Details"
                                        required="{Boolean}false">
                                        <field
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/container"
                                            emptyText="Books Details"
                                            name="./bookdetailswithmap">
                                            <items jcr:primaryType="nt:unstructured">
                                                <book
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    emptyText="Book Name"
                                                    fieldLabel="Book Name"
                                                    name="./bookname"/>
                                                <subject
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    emptyText="Book Subject"
                                                    fieldLabel="Book Subject"
                                                    name="./booksubject"/>
                                                <published
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    emptyText="Publish Year"
                                                    fieldLabel="Publish Year"
                                                    name="./publishyear"/>
                                            </items>
                                        </field>
                                    </bookdetailswithmap>

 Sling Model(Only method which return multifield values. get resource using annotation)

    public List<Map<String, String>> getBookDetailsWithMap() {
        List<Map<String, String>> bookDetailsMap=new ArrayList<>();
        try {
            Resource bookDetail=componentResource.getChild("bookdetailswithmap");
            if(bookDetail!=null){
                for (Resource book : bookDetail.getChildren()) {
                    Map<String,String> bookMap=new HashMap<>();
                    bookMap.put("bookname",book.getValueMap().get("bookname",String.class));
                    bookMap.put("booksubject",book.getValueMap().get("booksubject",String.class));
                    bookMap.put("publishyear",book.getValueMap().get("publishyear",String.class));
                    bookDetailsMap.add(bookMap);
                }
            }
        }catch (Exception e){
            LOG.info("\n ERROR while getting Book Details {} ",e.getMessage());
        }
        LOG.info("\n SIZE {} ",bookDetailsMap.size());
        return bookDetailsMap;
    }

Sightly (pseudo code) to print multifield values. Update as per your need. 

    <div data-sly-list.item="${books.bookDetailsWithMap}">
        ---------------Book : ${itemList.count}--------------
        <p> Book : <b>${item.bookname} </b></p>
        <p> Subject : <b>${item.booksubject}</b> </p>
        <p> Publish : <b>${item.publishyear}</b> </p>
    </div>

Sling Model - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/models/im...
Component - https://github.com/aemgeeks1212/aemgeeks/tree/master/ui.apps/src/main/content/jcr_root/apps/aemgeeks...

If you are interested. Links to video tutorials.
Multifield - https://youtu.be/TJaAdbkyPJQ
Nested Multifield - https://youtu.be/Lm6o5JDNiqs
Validation for Multifield - https://youtu.be/tsd8s8UMBRY 

Avatar

Community Advisor

@Nandheswara 

 

In Sling Model  annotate your multifiled with @ChildResource with reference List<T>

Write a Sling Model for Multi Field item. Ex: MultiFieldItem is model for multifield item which will have all properties of each item.

@ChildResource
private List<MultiFieldItem> myMultiField;

Now you can iterate the myMultiField list it HTL or in Sling Model to get data.