Description
As a developer:
I want the carousel component to dynamically pull content from content fragments that are set in the components dialog properties o that the content can be updated in the fragments and automatically displayed in the carousel.
Acceptance Criteria:
The author sets the list of content fragments in the components dialog then the component fetches content from selected content fragments.
Content fragment details (e.g., title, description, images) are displayed correctly within each slide.
Changes in content fragments reflect in the carousel component without manual updates.
Can anyone provide any example or anything related to this will be really helpful and here what is the exact expections would help me.
Regards
Vinith M
Solved! Go to Solution.
Views
Replies
Total Likes
Hi @Vineeee
On simple straight forwars way yhat I see is this:
Hi @Vineeee
On simple straight forwars way yhat I see is this:
PS: Sorry for the typos. I responded from mobile, and it seams the responsive site does not have Edit option to my comment.
Hi @Vineeee
Please find the below example you are looking for -
1. Provide a CF path in dialog as below
GitHub core component examples :
2. Read the CF path in sling model, retrieve the properties using Content Fragment API and implement getters and setters for title, description and images
Core component content fragment is implemented this way, you can check the implementation and override the component
Hope this helps !
Thanks
Prathyusha
Thank you @PRATHYUSHA_VP it did help me understand much more.
Thank you @arunpatidar I will try to do it.
Hi @arunpatidar
Can u please explain with some more steps it would be really helpful.Add items as Content Fragments should it be done programatically from Sling Model? or any other way.
Hi @arunpatidar,
Thank you for your suggestion! Could you please explain the steps in more detail? Specifically:
Hi @Vinithm2
Step1 - Allow content fragment component in the allowed component list from Carousel component 's policy
Step2 - Identify content fragment Items to create card and write CSS , step mentioned by @PRATHYUSHA_VP
you don't need to override anything until you can manage styling of content fragment model using CSS.
Hi @arunpatidar Following our earlier conversation, I successfully implemented the functionality to pick images from Content Fragments and generate responsive renditions using srcsetfor different devices. However, I want the image widths to be dynamically driven by the content policy instead of being hardcoded. Despite trying multiple approaches, I couldn’t achieve this.
Direct Policy-Based Widths:
Processing CF Images with Core Image Model:
Both approaches were unsuitable for seamlessly achieving the requirement.
import com.adobe.cq.dam.cfm.ContentFragment;
import com.adobe.cq.dam.cfm.FragmentData;
import com.adobe.cq.wcm.core.components.models.Carousel;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class DynamicCardCarouselModel implements Carousel {
@SlingObject
private ResourceResolver resourceResolver;
@ValueMapValue
private String[] contentFragments;
private List<ContentFragmentData> fragmentDataList;
@PostConstruct
protected void init() {
fragmentDataList = new ArrayList<>();
if (contentFragments == null || contentFragments.length == 0) {
return;
}
for (String fragmentPath : contentFragments) {
if (StringUtils.isNotBlank(fragmentPath)) {
processFragmentPath(fragmentPath);
}
}
}
/**
* Processes a single Content Fragment path and extracts its data if valid.
*
* @param fragmentPath The Content Fragment path to process.
*/
private void processFragmentPath(String fragmentPath) {
Resource fragmentResource = resourceResolver.getResource(fragmentPath);
if (fragmentResource == null) {
return;
}
ContentFragment contentFragment = fragmentResource.adaptTo(ContentFragment.class);
if (contentFragment == null) {
return;
}
ContentFragmentData data = extractContentFragmentData(contentFragment);
if (data != null) {
fragmentDataList.add(data);
}
}
/**
* Extracts relevant data from a Content Fragment.
*
* @param contentFragment The content fragment to extract data from.
* @return A ContentFragmentData object containing the fragment's title, description, image path, and link URL.
*/
private ContentFragmentData extractContentFragmentData(ContentFragment contentFragment) {
String title = getFragmentStringProperty(contentFragment, "cardTitle");
String description = getFragmentStringProperty(contentFragment, "cardDescription");
String imagePath = getFragmentStringProperty(contentFragment, "cardImage");
String linkURL = getFragmentStringProperty(contentFragment, "cardLinkURL");
return new ContentFragmentData(title, description, imagePath, linkURL);
}
/**
* Retrieves a string property value from a Content Fragment.
*
* @param contentFragment The content fragment.
* @param propertyName The name of the property to retrieve.
* @return The string value of the property, or an empty string if not found.
*/
private String getFragmentStringProperty(ContentFragment contentFragment, String propertyName) {
if (contentFragment.hasElement(propertyName)) {
FragmentData fragmentData = contentFragment.getElement(propertyName).getValue();
return fragmentData.getValue(String.class);
}
return "";
}
/**
* Exposes the list of content fragment data for rendering.
*
* @return List of ContentFragmentData objects.
*/
public List<ContentFragmentData> getFragmentDataList() {
return fragmentDataList != null ? fragmentDataList : Collections.emptyList();
}
/**
* Inner class representing the data of a content fragment.
*/
public static class ContentFragmentData {
private final String title;
private final String description;
private final String imagePath;
private final String linkURL;
public ContentFragmentData(String title, String description, String imagePath, String linkURL) {
this.title = title;
this.description = description;
this.imagePath = imagePath;
this.linkURL = linkURL;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getImagePath() {
return imagePath;
}
public String getLinkURL() {
return linkURL;
}
}
}
<sly data-sly-use.dynamicCarousel="com.v2.core.models.DynamicCardCarouselModel">
<sly data-sly-use.inPageNavModel="com.v2.core.models.InPageNavigationModel">
<div class="cmp-card-carousel" data-cmp-is="card-carousel" id="${carousel.id}">
<div class="cmp-card-carousel__wrapper" data-sly-attribute.id="${inPageNavModel.currentResourceInPageNavID}">
<div class="cmp-card-carousel__controls">
<button class="swiper-button swiper-button--prev">
<span class="visually-hidden">Previous</span>
</button>
<button class="swiper-button swiper-button--next">
<span class="visually-hidden">Next</span>
</button>
</div>
<div class="cmp-card-carousel__swiper swiper">
<sly data-sly-test="${dynamicCarousel.fragmentDataList.size > 0}">
<div class="swiper-wrapper" data-sly-list.fragment="${dynamicCarousel.fragmentDataList}">
<div class="swiper-slide" role="tabpanel" data-cmp-hook-carousel="item" aria-roledescription="slide">
<div class="cmp-card--carousel-item-inner${fragment.linkURL ? ' clickable' : ''}">
<div class="cmp-card__wrapper">
<div class="cmp-card__header">
<img src="${fragment.imagePath}"
srcset="${fragment.imagePath}?width=320 320w,
${fragment.imagePath}?width=520 520w,
${fragment.imagePath}?width=960 960w"
sizes="(max-width: 480px) 320px,
(min-width: 481px) and (max-width: 768px) 640px,
(min-width: 769px) 960px"
alt="${fragment.title}">
</div>
<div class="cmp-card__contents">
<h5 class="cmp-card__title">
<a href="${fragment.linkURL}" target="_blank">${fragment.title}</a>
</h5>
<div class="cmp-card__description">
<p>${fragment.description @ context='html'}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</sly>
</div>
<div class="cmp-card-carousel__scrollbar">
<div class="swiper-scrollbar"></div>
</div>
</div>
</div>
</sly>
</sly>
@Vineeee Did you find the suggestions helpful? Please let us know if you require more information. Otherwise, please mark the answer as correct for posterity. If you've discovered a solution yourself, we would appreciate it if you could share it with the community. Thank you!
Views
Replies
Total Likes
Yes It was really helpful but i do not have the option to mark as correct answer please help me or if possible mark as the correct answer
Views
Replies
Total Likes
Views
Likes
Replies