Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

SOLVED

AEM Multi-fields not returning from Sling Model

SocialTaylor
Level 3
Level 3

Hello AEM Heads!

 

I have been wracking my brain on this for well over a week now and figured I'd reach out and try to see what I am doing wrong. I have set-up a multi-field in my cq:dialog for this component and, as you can see, they are being are stored correctly in crxdelite, but when I have tried to pull them out and into the HTML, I am not seeing them being displayed. You can see the code below, where it is being called, the Model I have created, and how it's being stored. I did check the logs and see that I was receiving an Error from the Model and that the multi-field size was 0, however, since I am getting the "cards" item in my model, I'm not sure why it's not counting those?

 

Just not really sure what to do as I've tried a lot of tweaking to no luck. Any insight would be greatly appreciated!!

 

Screen Shot 2021-08-25 at 10.03.30 PM.pngScreen Shot 2021-08-25 at 10.03.40 PM.pngScreen Shot 2021-08-25 at 10.04.03 PM.pngScreen Shot 2021-08-25 at 10.04.32 PM.pngScreen Shot 2021-08-25 at 10.07.09 PM.pngScreen Shot 2021-08-25 at 10.08.02 PM.pngScreen Shot 2021-08-25 at 10.50.57 PM.png

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution
Umesh_Thakur
Correct answer by
Community Advisor
Community Advisor

First of all you should not make your sling model adaptables to SlingHttpServletRequest specially to get value from multifiled. then you made a mistake by trying to directly inject your resource for multifield. These are some mistake you have done prima-facie.

Please go thru the below article which fits 100% in your requirement.

https://helpx.adobe.com/experience-manager/using/aem64_htl_repeat_slingmodel.html

Just see the sling model 

 

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.apache.sling.settings.SlingSettingsService;
 
@Model(adaptables = Resource.class)
public class Multifield {
 
 // Inject the products node under the current node
 public Resource products;
 
 // No need of a post construct as we don't have anything to modify after the
 // model is constructed
}
 

and HTL code like

<div
    data-sly-use.multiItems="aem.community.mf.core.models.Multifield">
    <div data-sly-list.head="${multiItems.products.listChildren}">
 
 
  <div style="height:250px;"><img src=${head.pathbr} height=200 width=270 style="padding:4px"/><h2>${head.product}</h2>
                             <p>${head.desc}</p>
 
                             </div>
                             <hr>
 
   </div>
</div>

 

Hope this will help.

Umesh Thakur

View solution in original post

0 Replies
Umesh_Thakur
Correct answer by
Community Advisor
Community Advisor

First of all you should not make your sling model adaptables to SlingHttpServletRequest specially to get value from multifiled. then you made a mistake by trying to directly inject your resource for multifield. These are some mistake you have done prima-facie.

Please go thru the below article which fits 100% in your requirement.

https://helpx.adobe.com/experience-manager/using/aem64_htl_repeat_slingmodel.html

Just see the sling model 

 

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.apache.sling.settings.SlingSettingsService;
 
@Model(adaptables = Resource.class)
public class Multifield {
 
 // Inject the products node under the current node
 public Resource products;
 
 // No need of a post construct as we don't have anything to modify after the
 // model is constructed
}
 

and HTL code like

<div
    data-sly-use.multiItems="aem.community.mf.core.models.Multifield">
    <div data-sly-list.head="${multiItems.products.listChildren}">
 
 
  <div style="height:250px;"><img src=${head.pathbr} height=200 width=270 style="padding:4px"/><h2>${head.product}</h2>
                             <p>${head.desc}</p>
 
                             </div>
                             <hr>
 
   </div>
</div>

 

Hope this will help.

Umesh Thakur

View solution in original post

SocialTaylor
Level 3
Level 3

Hello @Umesh_Thakur !

 

Thank you all for your responses. I have gone through all the responses and tested each one, however, I am stuck with an error now being output. As you can see, my code has been updated to Inject the cards as a Resource, I've removed the SlingHttpServletRequest, and I have tested by removing my getHeader function and even making a very simple model that only returns the cards, but this my error:

CANNOT GET DEFAULTSLINGSCRIPT: NO USE PROVIDER COULD RESOLVE IDENTIFIER COM.MOVEMENTMORTGAGE.CORE.MODELS.LAYOUTINFOGRAPHCARDGRID

 

Any ideas??

 

Screen Shot 2021-08-26 at 10.47.21 AM.pngScreen Shot 2021-08-26 at 10.47.31 AM.pngScreen Shot 2021-08-26 at 10.48.00 AM.pngScreen Shot 2021-08-26 at 10.48.09 AM.pngScreen Shot 2021-08-26 at 10.48.27 AM.png

Veena_Vikram
Community Advisor
Community Advisor

@SocialTaylor Your code looks good to me now. If everything goes well, this has to execute. There can be few weird situations. Something like your jar bundles are not updated. Just for a cross verification, remove the bundle package completely from your system/console and reinstall and check if this resolves your issue. Adding some references below for this kind of issue. 

 

https://github.com/adobe/aem-component-generator/issues/19#issuecomment-559168608

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/no-use-provider-could-reso... 

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/getting-error-msg-no-use-p...  ( this might not be valid in your case)

Umesh_Thakur
Community Advisor
Community Advisor

yes I can see issue in your code in the model annotation that is, you need to put adapters value in your case as you are inheriting one interface in your model.

You already had done in your existing code at line #21. so your final @Model will be like:

 

@Model(

adaptables = {Resource.class}, 

adapters = {HeroBannerComponent.class}, 

defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)

public class HeroBannerComponentImpl implements HeroBannerComponent {

}

 

 

Hope this helps.

Umesh Thakur 

SocialTaylor
Level 3
Level 3

Hey @Umesh_Thakur !

 

That was exactly it! Once I updated that, everything worked like a charm. My last inquiry in this is for nested items. Would I be able to access a node called links under the cards in the model using something similar like:

@Inject
@Optional
Resource links;

@Override
public Resource getLinks() {
    return links;
}

And then in the HTL like so?

<a data-sly-repeat.button="${item.links.listChildren}">

 

Or would that require a different model altogether? I would assume that, since you are calling that under item.links that it would grab the correct nodes?

 

Thank you also for all the help! This has been a huge learning curve on my end, so I greatly appreciate it!

Umesh_Thakur
Community Advisor
Community Advisor

No need to have a different model for the same, same model will work here.

Only you need to get the Iterator object of the parent resource by calling the listChildren of it like:

Iterator iterator = parentResource.listChildren();

while(iterator.hasNext())

{

     Resource childResource = iterator.next();// here you have your child resources

// do what ever you want for child resources.

}

 

but will be better this if you create a list instead of passing the child resource to the sightly.

 

Hope this will help.

Umesh Thakur

SocialTaylor
Level 3
Level 3

Hey @Umesh_Thakur !

 

Would it be something like that or is there a better way to include those links under my getCards function rather than a new get function? I think I may not be sure where to place it.

package com.movementmortgage.core.models.impl;

import java.util.Iterator;
import java.util.List;

import javax.inject.Inject;

import com.movementmortgage.core.models.LayoutInfographCardGrid;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;

@Model(
    adaptables = {Resource.class},
    adapters = {LayoutInfographCardGrid.class},
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class LayoutInfographCardGridImpl implements LayoutInfographCardGrid {

    @Inject
    @Optional
    Resource cards;

    @ValueMapValue
    public String header;

    @Override
    public String getHeader() {
        return header;
    }

    @Override
    public Resource getCards() {
        return cards;
    }

    @Override
    public List getLinks() {
        Iterator iterator = cards.listChildren();

        List<Resource> links;
        
        while(iterator.hasNext()) {
            links.add((Resource)iterator.next());
        }

        return links;
    }
}

Thank you so much for all the help on this again! I really do appreciate it.

Taylor

Kiran_Vedantam
Community Advisor
Community Advisor

Hi @SocialTaylor,

 

In the model, you are adapting it with SlingHttpRequest and trying to inject the multi field resource which will not work.

Try adding the Resource as one of the adatables (along with the request) or try this

@Inject @Via("resource")

Resource componentResource;

 

It should work.

Relevant URL's:

  1. https://sling.apache.org/documentation/bundles/models.html
  2. https://stackoverflow.com/questions/54454534/what-is-the-significance-of-declaring-a-sling-model-as-...

Hope this helps.

Thanks,

Kiran Vedantam.

Veena_Vikram
Community Advisor
Community Advisor

@SocialTaylor There are few minor adjustments you have to do to your logic to get this work . Find below the sample model I did to just implement the very basic of your logic

Veena_Vikram_1-1629969200286.png

 

1. First point you have to understand is the naming conventions. Since your component's multifield has name cards , as you can see in your node structure , each items starting from item0 , item1,.... will get added to a node/ resource by name "cards" . So basically you have to inject the resource which has the name as "cards" .

Below image explains the nodes as per my component structure

Veena_Vikram_2-1629969742870.png

 

 In your code, at line 27,  you are trying to inject a resource componentResource . I am not sure from where you are referring that name. If we have to go by the names you have given and the nodes which are created , you should have been injecting the Resource as "cards"

2. Now as have I explained in another forum post https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/usage-of-via-in-sling-mode... you have to use @Via("resource") to get any Resources in your model if you are adapting your model using SlingHttpServletRequest.class . 


But I think , since you don't need any request object in your model , you can better avoid using SlingHttpServletRequest.class and use only Resource.class ( Request is reccomended only when you need to use any object which Resource cannot provide) So may be you can rewrite your adaptable as something like below

Veena_Vikram_3-1629971725794.png

If you notice , in this case , you don't have to Inject it via resource , because your model is adapted via Resource.


Also , I think the logic you have written in the post construct is not needed. It can be simplified and done directly in the HTL as below 

@Inject
@Via("resource")

Resource cards;

public Resource getCards() {

return cards;
}


Return your cards resource via a getCards() method in the Model and do the below in the HTL

<div
data-sly-use.model="com.learn.practice.aem.core.models.MultifieldSampleModel">
<div data-sly-list.children="${model.cards.listChildren}">
${children.headerText}

${children.headerImage}
${children.content}
</div>
</div>

Depending on your requirement and FE rendering play around with this values in the HTL.

   Hope this helps. I tried to explain it the best I could, but still if you have any questions please let me know. Hope you get it resolved asap. Next time  don't wait for a week , but an extra eye might help to catch the issues 🙂 Always feel free to come back to forum if you face any issues 🤗 

Veena ✌