Extend Teaser Component using Sling Model Delegate Pattern | Community
Skip to main content
subrato_kha
Level 4
November 24, 2020
Question

Extend Teaser Component using Sling Model Delegate Pattern

  • November 24, 2020
  • 4 replies
  • 776 views

Hi,

I have been trying to extend Teaser component behaviour using Sling Delegate Pattern. I want to overwrite the linkUrl property behaviour but it is not working as expected. The link on the image is always the one which is configured on the component but I expect it to be overwritten by the static link from the below overwritten method.

 

import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.wcm.core.components.models.ListItem;
import com.adobe.cq.wcm.core.components.models.Teaser;
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.via.ResourceSuperType;

import java.util.List;

@Model(
adaptables = SlingHttpServletRequest.class,
adapters = {Teaser.class, ComponentExporter.class},
resourceType = "myproject/components/content/teaser",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class CustomTeaserImpl implements Teaser {

@Self
@Via(type = ResourceSuperType.class)
private Teaser teaser;

@Override
public String getLinkURL() {
return "/content/subrato/foo";
}

/**
* Checks if the teaser has Call-to-Action elements
*
* @return {@code true} if teaser has CTAs, {@code false} otherwise
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public boolean isActionsEnabled() {
return this.teaser.isActionsEnabled();
}

/**
* Returns the list of Call-to-Action elements
*
* @return the list of CTAs
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public List<ListItem> getActions() {
return this.teaser.getActions();
}

/**
* Returns the image resource for this teaser.
*
* @return the image resource for this teaser or {@code null}
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public Resource getImageResource() {
return this.teaser.getImageResource();
}

/**
* Checks if the link on the image is hidden.
*
* @return {@code true} if link is hidden on the image, {@code false} otherwise
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public boolean isImageLinkHidden() {
return this.teaser.isImageLinkHidden();
}

/**
* Returns this teaser's pretitle, if one was defined.
*
* @return the teaser's pretitle or {@code null}
*
* @since com.adobe.cq.wcm.core.components.models 12.12.0
*/
@Override
public String getPretitle() {
return this.teaser.getPretitle();
}

/**
* Returns this teaser's title, if one was defined.
*
* @return the teaser's title or {@code null}
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public String getTitle() {
return this.teaser.getTitle();
}

/**
* Checks if the link on the title is hidden.
*
* @return {@code true} if link is hidden on the title, {@code false} otherwise
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public boolean isTitleLinkHidden() {
return this.teaser.isTitleLinkHidden();
}

/**
* Returns this teaser's description, if one was defined.
*
* @return the teaser's description or {@code null}
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public String getDescription() {
return this.teaser.getDescription();
}

/**
* Returns the HTML element type (h1-h6) used for the title.
*
* @return the element type
*
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public String getTitleType() {
return this.teaser.getTitleType();
}

/**
* @since com.adobe.cq.wcm.core.components.models 12.4.0
*/
@Override
public String getExportedType() {
return this.teaser.getExportedType();
}
}

@theo_pendle 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

4 replies

SureshDhulipudi
Community Advisor
Community Advisor
November 24, 2020

declare LinkURL ValueMap variable

 

@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)

private String linkURL;

 

 

====

The best practice is to declare interface and then implement:

1) CustomTeaser Interface

 

public interface CustomTeaser extends Teaser {

 default String getLinkURL() {

      ///

}

 

----

2) Implement CustomTeaser interface

 

@Model(
adaptables = SlingHttpServletRequest.class,
adapters = {CustomTeaser.class,Teaser.class, ComponentExporter.class},
resourceType = "myproject/components/content/teaser",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class CustomTeaserImpl implements CustomTeaser {


@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)

private String linkURL;

@9944223
public String getLinkURL() {
return "/content/subrato/foo";
}
}

subrato_kha
Level 4
November 25, 2020
@sureshdhulipudi : There is no new methods getting introduced so new interface doesnt have any value, but yes the way mentioned injecting the linkURL can be better done by Delegate pattern where you can get the link url by this.teaser.getLinkUrl(). Inspite of using this method to update the url to a static link, the actual link on the image of the teaser component always takes the link from the properties but not the link which I modified in the backend.
arunpatidar
Community Advisor
Community Advisor
November 24, 2020
@Model(adaptables = SlingHttpServletRequest.class, adapters = {Teaser.class,CustomTeaser.class}, resourceType = MyConstants.TEASER_RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class CustomTeaser implements Teaser { @Self @Via(type = ResourceSuperType.class) private Teaser teaser; private String newLinkUrl; @PostConstruct protected void init() { newLinkUrl = "/content/mypro/lang/somepath"; } public String getLinkURL() { return newLinkUrl; } }
Arun Patidar
subrato_kha
Level 4
November 25, 2020
@arunpatidar : using this approach the postconstruct is not getting invoked
Manjunath_K
Level 7
November 24, 2020

Hi @subrato_kha,

The image section on Teaser component will be rendered from the proxy component defined with imageDelegate property on component node. so, adding custom Sling Model for Teaser component using Sling Delegate Pattern & passing static link from overridden method will not work in this case because link on image will be referred from Sling Model object "com.adobe.cq.wcm.core.components.models.Image"(i.e. ${image.link}).

 

imageDelegate property on Teaser component:

refer this : https://github.com/adobe/aem-core-wcm-components/blob/master/content/src/content/jcr_root/apps/core/wcm/components/teaser/v1/teaser/README.md

 

 

 

Hope this helps!

Manjunath_K
Level 7
November 25, 2020

Hi @subrato_kha,

The image section on Teaser component will be rendered from the proxy component defined with imageDelegate property on component node. so, adding custom Sling Model for Teaser component using Sling Delegate Pattern & passing static link from overridden method will not work in this case because link on image will be referred from Sling Model object "com.adobe.cq.wcm.core.components.models.Image" (i.e. ${image.link})

 

imageDelegate property on Teaser component:

refer this : https://github.com/adobe/aem-core-wcm-components/blob/master/content/src/content/jcr_root/apps/core/wcm/components/teaser/v1/teaser/README.md

 

 

 

Hope this helps!