Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Foundation component vs Core Component in AEM6.5

Avatar

Level 6

Hi All,

 

there is a requirement where I need to get the one static HTML into another HTML as like iframe.

Previously I planned to used External Component (OOTB) : /libs/foundation/components/external

But I came to know foundation component is now deprecated in AEM6.5,

 

From some article got to know that we can use core component (Embed) instead of foundation, I am not sure about embed component, can we use embed to include static HTML in another HTML?

 

So need your input on the same..

Scenario: 

like I have uploaded static HTML file under /content/dam/folder and related CSS, JS, fonts and images within same /content/dam/folder , and in external component i have given path /content/dam/folder/index.html, so that It'll render in a page as i-frame

 

Is it fine to use External Component (Foundation) in AEM6.5 or should go for Embed component or is there another component which provide functionality of iframe, and how to make use of it.

 

Thanks,

 

@kautuk_sahni   @Theo_Pendle @arunpatidar @Ankur_Khare  @BrianKasingli 

Topics

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

1 Accepted Solution

Avatar

Correct answer by
Level 10

Hi @tushaar_srivastava,

I'm a bit confused by your question. It sounds like you have some raw HTML you want to include in a page, but this have nothing to do with an iframe 

An iframe lets you open a window towards another web page, with HTML, JS, CSS and everything running inside the iframe.

A HTML snippet just injects a bit of HTML into your current page's DOM.

These are two very different things, so watch out! 

However, since you mentioned a HTML in your DAM, this is my solution to extend the AEM Core Component Embed to render HTML from a DAM asset rather than from the contents of the HTML textarea.

If you created your project using the AEM Maven Archetype you should already have an Embed component proxied from AEM Core Components. You will find it here: /apps/demo/components/content/embed.

In order to create our own method of rendering HTML we will have to create a Sling Model which will map to our version of the Embed component. 

Here is the model:

 

import com.adobe.cq.wcm.core.components.models.Embed;
import com.day.cq.dam.api.Asset;
import lombok.experimental.Delegate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.via.ResourceSuperType;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
@Model(adaptables = {Resource.class, SlingHttpServletRequest.class}, adapters = Embed.class, resourceType = "demo/components/content/embed")
public class CustomEmbed implements Embed {

    @Delegate(types = Embed.class, excludes = DelegateExclusion.class)
    @Self
    @Via(type = ResourceSuperType.class)
    private Embed delegate;

    @Self
    private SlingHttpServletRequest request;

    @PostConstruct
    public void init() {
        log.debug("Hello");
    }

    @ValueMapValue(name = PN_HTML, injectionStrategy = InjectionStrategy.OPTIONAL)
    private String html;

    @Override
    public String getHtml() {
        if (StringUtils.isNotEmpty(html)) {
            final Resource assetResource = request.getResourceResolver().getResource(html);
            if (assetResource != null) {
                final Asset asset = assetResource.adaptTo(Asset.class);
                if (asset != null) {
                    final String mimeType = asset.getMimeType();
                    return "text/html".equals(mimeType) ? readHtmlStringFromAsset(asset) : "";
                } else {
                    log.error("Unable to adapt resource <{}> to an Asset.", html);
                }
            } else {
                log.error("Unable to find resource <{}>.", html);
            }
        }
        return "";
    }

    private String readHtmlStringFromAsset(final Asset htmlAsset) {
        try {
            return IOUtils.toString(htmlAsset.getOriginal().getStream(), StandardCharsets.UTF_8.name());
        } catch (final IOException e) {
            log.warn("Could not read asset <{}> to HTML string", htmlAsset.getPath());
            return "";
        }
    }

    private interface DelegateExclusion {
        String getHtml();
    }
}

 

Let's take a look at the most important parts:

  • By setting the resourceType to our Embed's resourceType, we tell Sling to map our model to the component. This way we simply "hijack" the original behaviour, without having to write a new cq:dialog or HTL files 
  • The @Delegate annotation is from Lombok. It's a shorthand way of implementing the delegation pattern.
    • As you can see, we delegate every method to AEM Core Component's implementation of the Embed model except the getHtml() method (by using the DelegationExclusion inner interface).
    • We dont have to use a ModelFactory to fetch an instance of the AEM Core Component's implementation of the Embed thanks to the @Self and @Via(type = ResourceSuperType.class) annotations.
  • We implement our own getHtml() method which fetches an Asset from the DAM and reads it as a binary file.

Now for the proof! Watch me test it with this GIF:

Peek 2020-05-27 19-24.gif

Of course, I suggest changing the field type of the HTML field from a textarea to a textfield 

Hope that helps!

View solution in original post

2 Replies

Avatar

Correct answer by
Level 10

Hi @tushaar_srivastava,

I'm a bit confused by your question. It sounds like you have some raw HTML you want to include in a page, but this have nothing to do with an iframe 

An iframe lets you open a window towards another web page, with HTML, JS, CSS and everything running inside the iframe.

A HTML snippet just injects a bit of HTML into your current page's DOM.

These are two very different things, so watch out! 

However, since you mentioned a HTML in your DAM, this is my solution to extend the AEM Core Component Embed to render HTML from a DAM asset rather than from the contents of the HTML textarea.

If you created your project using the AEM Maven Archetype you should already have an Embed component proxied from AEM Core Components. You will find it here: /apps/demo/components/content/embed.

In order to create our own method of rendering HTML we will have to create a Sling Model which will map to our version of the Embed component. 

Here is the model:

 

import com.adobe.cq.wcm.core.components.models.Embed;
import com.day.cq.dam.api.Asset;
import lombok.experimental.Delegate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.via.ResourceSuperType;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
@Model(adaptables = {Resource.class, SlingHttpServletRequest.class}, adapters = Embed.class, resourceType = "demo/components/content/embed")
public class CustomEmbed implements Embed {

    @Delegate(types = Embed.class, excludes = DelegateExclusion.class)
    @Self
    @Via(type = ResourceSuperType.class)
    private Embed delegate;

    @Self
    private SlingHttpServletRequest request;

    @PostConstruct
    public void init() {
        log.debug("Hello");
    }

    @ValueMapValue(name = PN_HTML, injectionStrategy = InjectionStrategy.OPTIONAL)
    private String html;

    @Override
    public String getHtml() {
        if (StringUtils.isNotEmpty(html)) {
            final Resource assetResource = request.getResourceResolver().getResource(html);
            if (assetResource != null) {
                final Asset asset = assetResource.adaptTo(Asset.class);
                if (asset != null) {
                    final String mimeType = asset.getMimeType();
                    return "text/html".equals(mimeType) ? readHtmlStringFromAsset(asset) : "";
                } else {
                    log.error("Unable to adapt resource <{}> to an Asset.", html);
                }
            } else {
                log.error("Unable to find resource <{}>.", html);
            }
        }
        return "";
    }

    private String readHtmlStringFromAsset(final Asset htmlAsset) {
        try {
            return IOUtils.toString(htmlAsset.getOriginal().getStream(), StandardCharsets.UTF_8.name());
        } catch (final IOException e) {
            log.warn("Could not read asset <{}> to HTML string", htmlAsset.getPath());
            return "";
        }
    }

    private interface DelegateExclusion {
        String getHtml();
    }
}

 

Let's take a look at the most important parts:

  • By setting the resourceType to our Embed's resourceType, we tell Sling to map our model to the component. This way we simply "hijack" the original behaviour, without having to write a new cq:dialog or HTL files 
  • The @Delegate annotation is from Lombok. It's a shorthand way of implementing the delegation pattern.
    • As you can see, we delegate every method to AEM Core Component's implementation of the Embed model except the getHtml() method (by using the DelegationExclusion inner interface).
    • We dont have to use a ModelFactory to fetch an instance of the AEM Core Component's implementation of the Embed thanks to the @Self and @Via(type = ResourceSuperType.class) annotations.
  • We implement our own getHtml() method which fetches an Asset from the DAM and reads it as a binary file.

Now for the proof! Watch me test it with this GIF:

Peek 2020-05-27 19-24.gif

Of course, I suggest changing the field type of the HTML field from a textarea to a textfield 

Hope that helps!

Avatar

Level 6

Thank you Theo, since I am using gradle project, could you please share me the above component package, would be great help to analyse more on this.

or any GitHub reference link.