Expand my Community achievements bar.

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

set core component property using sightly/sling model

Avatar

Level 1

Im constructing a custom component below is its layout.

 

Header section built using <h1>

Body section which uses out of the box embed component <div data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed'}"></div>

Footer that is again some HTML code

 

Im using embed component in the HTML mode where, I want to populate it content from a content fragment (that holds all the data in JSON format).

So when user drags and drops the stitched custom component, he will just choose the content fragment from dialog and it sling model will read it and return data for all the fields that the component is displaying using HTL. Now how do I feed data html content into the out of the box embed component either using HTL or sling model.

Topics

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

1 Accepted Solution

Avatar

Correct answer by
Level 9
To set the content of the out-of-the-box AEM Embed component using a content fragment, you can try and follow the below steps:

Step 1: Create a Sling Model for your Custom Component
Create a Sling Model class for your custom component that extends WCMUsePojo. This class will be responsible for fetching the content fragment data and providing it to the HTL script.
 
Sample code:

 

@Model(adaptables = SlingHttpServletRequest.class, adapters = CustomComponentModel.class, resourceType = CustomComponentModel.RESOURCE_TYPE)
public class CustomComponentModel extends WCMUsePojo {

    public static final String RESOURCE_TYPE = "your/component/resource/type";

    @JsonIgnore
    private ContentFragment contentFragment;

    @Override
    public void activate() throws Exception {
        contentFragment = getContentFragment();
    }

    public ContentFragment getContentFragment() {
        return contentFragment;
    }
}

 

 

Step 2: Fetch the Content Fragment Data
In the activate method of your Sling Model, fetch the content fragment data using the ResourceResolver and ContentFragmentManager. You can then store the ContentFragment object in a class variable for later use.
 
Sample code:

 

private ContentFragment getContentFragment() {
    ResourceResolver resourceResolver = getResourceResolver();
    ContentFragmentManager contentFragmentManager = resourceResolver.adaptTo(ContentFragmentManager.class);

    // Get the content fragment path from the component properties or dialog
    String contentFragmentPath = getProperties().get("contentFragmentPath", String.class);

    if (StringUtils.isNotBlank(contentFragmentPath)) {
        Resource contentFragmentResource = resourceResolver.getResource(contentFragmentPath);
        if (contentFragmentResource != null) {
            return contentFragmentManager.getContentFragment(contentFragmentResource);
        }
    }

    return null;
}

 

 

Step 3: Pass the Content Fragment Data to the Embed Component
In your HTL script, you can access the content fragment data from the Sling Model and pass it to the Embed component using the data-sly-resource attribute.
 
Sample code

 

<div data-sly-use.model="your.package.CustomComponentModel">
    <h1>${model.contentFragment.title}</h1>
    <div data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed', source=model.contentFragment.embedSource}"></div>
    <footer>${model.contentFragment.footer}</footer>
</div>

 

View solution in original post

4 Replies

Avatar

Level 10

Hi @Ashwin_KumarSr ,

 

To populate the out-of-the-box Embed component with data from a content fragment using HTL or a Sling model, you'll need to set the appropriate properties of the Embed component. Here's how you can achieve this:

  1. Using HTL: You can use HTL to dynamically set the properties of the Embed component based on the selected content fragment.

 

<!-- Your component markup -->
<div data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed',
                               src=myContentFragmentPath}"></div>

 

  1. In this example, myContentFragmentPath is a variable representing the path to the selected content fragment. You need to populate this variable in your dialog's Sling model.

  2. Using a Sling Model: You can use a Sling model to retrieve the data from the content fragment and pass it to your HTL markup.

    First, create a Sling model that retrieves the necessary data from the content fragment:

 

import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.wcm.core.components.models.Embed;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import javax.inject.Inject;

@Model(
    adaptables = Resource.class,
    adapters = { Embed.class, ComponentExporter.class },
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class MyEmbedModel implements Embed {

    @Inject
    private String src; // Path to your content fragment

    @Override
    public String getSrc() {
        return src;
    }
}

 

Then, in your HTL markup, use the Sling model to set the src property of the Embed component:

 

<div data-sly-use.embedModel="com.example.models.MyEmbedModel"
     data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed',
                               src=embedModel.src}"></div>

 

In this example, com.example.models.MyEmbedModel is the fully qualified class name of your Sling model.

By following either of these approaches, you can dynamically set the HTML content of the out-of-the-box Embed component based on the data from the selected content fragment. Ensure that your Sling model retrieves the necessary data from the content fragment and sets the appropriate properties of the Embed component.

 

Thanks!

Avatar

Level 1

Thanks for the detailed explanation. 

I tried the approach suggested but couldn't get it working. Here is the code

 

1) Sling Model

package com.sn.content.exp.core.models;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import com.adobe.cq.wcm.core.components.models.Embed;

@Model(adaptables = SlingHttpServletRequest.class, adapters = Embed.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class KBEmbedImpl implements Embed {

    private String src;

    public String getSrc() {
        return "<h1>From Sling Model</h1>";
    }

}

2) HTL

<sly data-sly-use.kb="com.sn.content.exp.core.models.KnowledgeArticle"
data-sly-use.kbembed="com.sn.content.exp.core.models.KBEmbedImpl">
    <div class="cmp-kb__body">
        <div data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed', src=kbembed.src}"></div>
    </div>
</sly>

 

With above code, the embed component doesn't show on the page the HTML Im passing via sling model, but the value I added through dialog from UI.

 

How is the src value being passed to embed component via data-sly-resource setting up the html field of the component. I did read about this core component couldn't find anything on src attribute.

Avatar

Correct answer by
Level 9
To set the content of the out-of-the-box AEM Embed component using a content fragment, you can try and follow the below steps:

Step 1: Create a Sling Model for your Custom Component
Create a Sling Model class for your custom component that extends WCMUsePojo. This class will be responsible for fetching the content fragment data and providing it to the HTL script.
 
Sample code:

 

@Model(adaptables = SlingHttpServletRequest.class, adapters = CustomComponentModel.class, resourceType = CustomComponentModel.RESOURCE_TYPE)
public class CustomComponentModel extends WCMUsePojo {

    public static final String RESOURCE_TYPE = "your/component/resource/type";

    @JsonIgnore
    private ContentFragment contentFragment;

    @Override
    public void activate() throws Exception {
        contentFragment = getContentFragment();
    }

    public ContentFragment getContentFragment() {
        return contentFragment;
    }
}

 

 

Step 2: Fetch the Content Fragment Data
In the activate method of your Sling Model, fetch the content fragment data using the ResourceResolver and ContentFragmentManager. You can then store the ContentFragment object in a class variable for later use.
 
Sample code:

 

private ContentFragment getContentFragment() {
    ResourceResolver resourceResolver = getResourceResolver();
    ContentFragmentManager contentFragmentManager = resourceResolver.adaptTo(ContentFragmentManager.class);

    // Get the content fragment path from the component properties or dialog
    String contentFragmentPath = getProperties().get("contentFragmentPath", String.class);

    if (StringUtils.isNotBlank(contentFragmentPath)) {
        Resource contentFragmentResource = resourceResolver.getResource(contentFragmentPath);
        if (contentFragmentResource != null) {
            return contentFragmentManager.getContentFragment(contentFragmentResource);
        }
    }

    return null;
}

 

 

Step 3: Pass the Content Fragment Data to the Embed Component
In your HTL script, you can access the content fragment data from the Sling Model and pass it to the Embed component using the data-sly-resource attribute.
 
Sample code

 

<div data-sly-use.model="your.package.CustomComponentModel">
    <h1>${model.contentFragment.title}</h1>
    <div data-sly-resource="${'embed' @ resourceType='core/wcm/components/embed/v2/embed', source=model.contentFragment.embedSource}"></div>
    <footer>${model.contentFragment.footer}</footer>
</div>

 

Avatar

Administrator

@Ashwin_KumarSr Did you find the suggestion helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni