Expand my Community achievements bar.

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.