Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.
SOLVED

Enhancing Image Component

Avatar

Level 3

Hi all,

I'm enhancing the image component by adding 2 extra fields Tablet image and Mobile image 
I have extended the Image sling models with my CustomImage interface but its not rendering the existing image functionality and my enhancement as well I'm not sure what is missing please help me on the same.

Have added Impl, Interface and HTL.

Interface:

package com.myproject.aem.myproject.division.core.components.models;
import org.osgi.annotation.versioning.ConsumerType;
import com.adobe.cq.wcm.core.components.models.Image;
@ConsumerType
public interface CustomImage extends Image  {
 
    public String getIsInline();
    public String getTabletImage();
    public String getMobileImage();


Thanks and Regards
Hari Prasath V

@arunk @arunpatidar @SantoshSai @LokeshVajrala @Saravanan_Dharmaraj @krati_garg 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @HariDo ,

I would use Delegation Pattern for Sling Models[0] where logic can be extended by using a Sling delegation pattern. "The Business logic for the core-components is implemented in Sling Models. In case it is necessary to customize the business logic to fulfill project specific requirements the delegation Pattern for Sling Models can be used"

Please refer[1],[2] similar example has been given for Image component.

  • The core component Image component relies on a class called ImageImpl to implement it’s model. You can use the delegation pattern to override the core component model’s behaviour and rely on the core Image interface to provide the methods you need:
    import com.adobe.cq.wcm.core.components.models.Image;
    import lombok.experimental.Delegate;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.api.resource.Resource;
    import org.apache.sling.models.annotations.DefaultInjectionStrategy;
    import org.apache.sling.models.annotations.Model;
    import org.apache.sling.models.annotations.Via;
    import org.apache.sling.models.annotations.injectorspecific.Self;
    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
    import org.apache.sling.models.annotations.via.ResourceSuperType;
    
    @Model(
    adaptables = {Resource.class, SlingHttpServletRequest.class},
    adapters = Image.class, // Adapts to the CC model interface
    resourceType = "demo/components/content/image", // Maps to OUR component, not the CC component
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL // No properties? No problem!
    )
    public class CustomImage implements Image { // We will be honoring the contract between the HTL and the model implementation
    
    @Self // Indicates that we are resolving the current resource
    @Via(type = ResourceSuperType.class) // Resolve not as this model, but as the model of our supertype (ie: CC Image)
    @Delegate(excludes = DelegationExclusion.class) // Delegate all our methods to the CC Image except those defined below
    private Image delegate;
    
    @ValueMapValue
    private boolean useOriginal; // This is a new property that we are introducing
    
    @ValueMapValue
    protected String fileReference; // This is the CC Image property that point to the image asset location in the DAM
    
    @Override
    public String getSrc() {
    // If useOriginal is checked, then serve the raw asset in full resolution, otherwise,
    // delegate this method to the CC Image
    return useOriginal ? fileReference : delegate.getSrc();
    }
    
    private interface DelegationExclusion { // Here we define the methods we want to override
    String getSrc(); // Override the method which determines the source of the asset
    }
    }

[0]: https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models

[1]: https://kiransg.com/2021/11/07/aem-core-component-delegation/

[2]: https://levelup.gitconnected.com/aem-extend-core-component-models-using-resource-type-association-an...

Hope thats helps!

Regards,

Santosh

View solution in original post

9 Replies

Avatar

Correct answer by
Community Advisor

Hi @HariDo ,

I would use Delegation Pattern for Sling Models[0] where logic can be extended by using a Sling delegation pattern. "The Business logic for the core-components is implemented in Sling Models. In case it is necessary to customize the business logic to fulfill project specific requirements the delegation Pattern for Sling Models can be used"

Please refer[1],[2] similar example has been given for Image component.

  • The core component Image component relies on a class called ImageImpl to implement it’s model. You can use the delegation pattern to override the core component model’s behaviour and rely on the core Image interface to provide the methods you need:
    import com.adobe.cq.wcm.core.components.models.Image;
    import lombok.experimental.Delegate;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.api.resource.Resource;
    import org.apache.sling.models.annotations.DefaultInjectionStrategy;
    import org.apache.sling.models.annotations.Model;
    import org.apache.sling.models.annotations.Via;
    import org.apache.sling.models.annotations.injectorspecific.Self;
    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
    import org.apache.sling.models.annotations.via.ResourceSuperType;
    
    @Model(
    adaptables = {Resource.class, SlingHttpServletRequest.class},
    adapters = Image.class, // Adapts to the CC model interface
    resourceType = "demo/components/content/image", // Maps to OUR component, not the CC component
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL // No properties? No problem!
    )
    public class CustomImage implements Image { // We will be honoring the contract between the HTL and the model implementation
    
    @Self // Indicates that we are resolving the current resource
    @Via(type = ResourceSuperType.class) // Resolve not as this model, but as the model of our supertype (ie: CC Image)
    @Delegate(excludes = DelegationExclusion.class) // Delegate all our methods to the CC Image except those defined below
    private Image delegate;
    
    @ValueMapValue
    private boolean useOriginal; // This is a new property that we are introducing
    
    @ValueMapValue
    protected String fileReference; // This is the CC Image property that point to the image asset location in the DAM
    
    @Override
    public String getSrc() {
    // If useOriginal is checked, then serve the raw asset in full resolution, otherwise,
    // delegate this method to the CC Image
    return useOriginal ? fileReference : delegate.getSrc();
    }
    
    private interface DelegationExclusion { // Here we define the methods we want to override
    String getSrc(); // Override the method which determines the source of the asset
    }
    }

[0]: https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models

[1]: https://kiransg.com/2021/11/07/aem-core-component-delegation/

[2]: https://levelup.gitconnected.com/aem-extend-core-component-models-using-resource-type-association-an...

Hope thats helps!

Regards,

Santosh

Avatar

Level 3

Hi @SantoshSai 

yes this helps but I'm not overriding I'm adding 3 new method's(fields) what should i do now i want the core component method's and my 3 new method's as well.

Please help me on this.

Regards
Hari Prasath

Avatar

Community Advisor

@HariDo - That's possible and mentioned in above link - "Delegate OOTB image component and add custom logic on existing methods like getWidth(), getHeight() and getSrcSet() and also add new method getCredit() and getSizes()."

Even if you are adding new methods you have to delegate(it's not overriding) it. Please go through above link to achieve your requirement.

Avatar

Level 3

Hi @SantoshSai 

I have modified and added a new method but its not rendering the values.
please correct me if i made any mistakes
CustomImage.java

 

Regards
Hari Do

Avatar

Community Advisor

@HariDo 

public String getTabletImage() {
      return "sampleTestForTableImage"
}

Can you try this and see if it is rendering in html

Avatar

Level 3

@SantoshSai 
It is not rendering the String "sampleTestForTableImage" so im making some mistake in my Models could you please sort it out.



package com.myproject.aem.myproject.division.core.components.models;

import com.adobe.cq.wcm.core.components.models.Image;


import lombok.experimental.Delegate;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.via.ResourceSuperType;



@Model(adaptables = { Resource.class, SlingHttpServletRequest.class },
     adapters = Image.class, resourceType = CustomImage.RESOURCE_TYPE,
      defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class CustomImage implements Image { 

    protected static final String RESOURCE_TYPE  ="myproject/myproject/components/content/image";

    @Self
    @Via(type = ResourceSuperType.class)
    @Delegate(excludes = DelegationExclusion.class)
    private Image image;

    
    @ValueMapValue
    private String mobileImage; //  Added this new property

    @ValueMapValue
    private String tabletImage; //  Added this new property

    @ValueMapValue
    private String isInline; //  Added this new property


    public String getTabletImage() {
        return "sampleTestForTableImage";
  }

    public String getIsInline() {
        return isInline;
    }

    public String getMobileImage() {
        return mobileImage;
    }


    private interface DelegationExclusion {
   
        }

    
}

 

 

Avatar

Level 3

@SantoshSai 
This worked there was an error in my bundle that's why its not working previously  the code is correct and thanks for suggesting this Delegation Method.

Regards 
Hari Do