Article summary

Summary

Discusses how to develop an AEM HTML Template Language (HTL - formerly known as Sightly) component that renders a newsletter whose content can be set by an AEM author using a Touch UI dialog.

Covers the following points:

  • how to build a responsive HTL component that renders a newsletter.
  • how to create custom application logic in the component so all of the component is displayed in the Touch UI while editing. 
  • how to use a granite/ui/components/coral/foundation/form/multifield and Sling Model to populate the body of a newsletter.

HTL is the AEM template language that can be used to replace use of JSP when developing an AEM component. HTL helps you to separate your design from your application logic. For more information, see Introduction to the HTML Template Language.

A special thank you to Ratna Kumar Kotla, a top AEM community member, for testing this article to ensure it works.

Digital Marketing Solution(s) Adobe Experience Manager 6.4
Audience Developer
Required Skills Java, HTML, JavaScript
Version 6.4

Note:

You can download an AEM package that contains the code used in this article. Download the package and deploy using package manager. The purpose of this code is to show the community these concepts in action. That is, it's to illustrate how to write a HTL component that renders a newsletter on Experience Manager 6.4. This community code is for teaching purposes only and not meant to go into production as is.

You can view the sample community application by using the following URL:

http://localhost:4502/editor.html/content/NewsLetter64/en.html (assuming you deploy on author)

 

Download

Note:

The Multifield used in this article is granite/ui/components/coral/foundation/form/multifield.

 

Introduction

You can create an Adobe Experience Manager 6.4 HTL component that renders a newsletter that you can distribute to your business audience. For example, consider a digital marketer that wants to promote events around a specific product. By creating an AEM newsletter, they can raise awareness of the product.

As an Experience Manager developer, you can create an Experience Manager HTL component that lets an author set all content for a newsletter, including images, text, links to other content such as videos, and so on. The following illustration shows the newsletter created in this development article.

newsletter
A Newsletter created from an HTL 6.4 component

As shown in the previous illustration, the HTL component renders a newsletter that consists of these sections:

  • text and image shown at the start of the newsletter
  • text that provides a summary of the newsletter
  • a repeating data section that contains the body of the newsletter. There can be many sections under the current issue section.
  • a section that lists previous editions

Content for each section is set by using a different tab in the Touch UI dialog. The following illustration shows the multi-field tab that populates body section.

Dialog
An AEM 6.4 Touch UI dialog that lets an author enter newsletter information

This development article steps you through how to build an AEM 6.4 HTL component by using an AEM Maven Archetype 13 project. That is, the Maven Archetype 13 project is used to build the OSGi bundle that is used with the HTL Newsletter component. This HTL component uses a Java class that uses Sling Models that handles the multifield. 

Create an AEM Maven 13 archetype project

You can create an Experience Manager archetype project by using the Maven archetype plugin. In this example, assume that the working directory is C:\AdobeCQ.

Maven
Files generated by Maven 13 Archetype

To create an Experience Manager archetype project, perform these steps:

1. Open the command prompt and go to your working directory (for example, C:\AdobeCQ).

2. Run the following Maven command:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeGroupId=com.adobe.granite.archetypes -DarchetypeArtifactId=aem-project-archetype -DarchetypeVersion=13 -DarchetypeCatalog=https://repo.adobe.com/nexus/content/groups/public/

3. When prompted, specify the following information:

  • groupId - NewsLetter64
  • artifactId - NewsLetter64
  • version - 1.0-SNAPSHOT
  • package - com.aem.newsletter
  • appsFolderName - NewsLetter64
  • artifactName - NewsLetter64
  • componentGroupName - NewsLetter64
  • confFolderName - NewsLetter64
  • contentFolderName - NewsLetter64
  • cssId - NewsLetter64
  • packageGroup - NewsLetter64
  • siteName - NewsLetter64

4. When prompted, specify Y.

5. Once done, you will see a message like:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:42 min
[INFO] Finished at: 2016-04-25T14:34:19-04:00
[INFO] Final Memory: 16M/463M
[INFO] ------------------------------------------------------------------------

6. Change the working directory to NewsLetter64 using cd NewsLetter64, and then enter the following command.

mvn eclipse:eclipse

After you run this command, you can import the project into Eclipse as discussed in the next section.

Add Java files to the Maven project using Eclipse

To make it easier to work with the Maven generated project, import it into the Eclipse development environment, as shown in the following illustration.

project
Eclipse Import Project Dialog

The Eclipse project that you work in to build the OSGi bundle that uses HTL API is NewsLetter64.core. You do not have to work in the other projects under NewsLetter64

Note:

Do not worry about the errors reported in Eclipse. It does not read the POM file where the APIs are resolved. You build the bundle with Maven. Eclipse is used to edit the Java files and the POM file.

The next step is to add a class named HeroSlingModel  to the package named com.aem.newsletter.core.models. The HeroSlingModel class uses an @inject annotation that injects a resource type (based on the node in the dialog) that corresponds to the granite/ui/components/coral/foundation/form/multifield (you are injecting the multifield into the Sling Model).

HeroSlingModel

The following Java code represents the HeroSlingModel class.  

package com.aem.newsletter.core.models;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
 
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
@Model(adaptables = Resource.class)
public class HeroSlingModel {
     
    private final Logger LOG = LoggerFactory.getLogger(getClass());
     // Inject the products node under the current node
    @Inject
    @Optional
    public Resource products;
  
    // No need of a post construct as we don't have anything to modify after the
    // model is constructed
}

Note:

In this example, products refers to the node located here: 

/apps/NewsLetter64/components/content/newsletter/cq:dialog/content/items/tabs/items/experience/items/columns/items/products/field

The name of the node must match the Resource variable name, otherwise the multifield will not be successfully injected into a Sling Model. 

Modify the Maven POM file

Add the following POM dependency to the POM file located at C:\AdobeCQ\NewsLetter64.

<dependency>
    <groupId>com.adobe.aem</groupId>
    <artifactId>uber-jar</artifactId>
    <version>6.4.0</version>
    <classifier>apis</classifier>
    <scope>provided</scope>
</dependency>
               
  <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-atinject_1.0_spec</artifactId>
       <version>1.0</version>
       <scope>provided</scope>
   </dependency>

When you add new Java classes under core, you need to modify a POM file to successfully build the OSGi bundle. You modify the POM file located at C:\AdobeCQ\NewsLetter64\core.

The following code represents this POM file.

<?xml version="1.0" encoding="UTF-8"?>
<!--
 |  Copyright 2017 Adobe Systems Incorporated
 |
 |  Licensed under the Apache License, Version 2.0 (the "License");
 |  you may not use this file except in compliance with the License.
 |  You may obtain a copy of the License at
 |
 |      http://www.apache.org/licenses/LICENSE-2.0
 |
 |  Unless required by applicable law or agreed to in writing, software
 |  distributed under the License is distributed on an "AS IS" BASIS,
 |  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  See the License for the specific language governing permissions and
 |  limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>NewsLetter64</groupId>
        <artifactId>NewsLetter64</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>NewsLetter64.core</artifactId>
    <packaging>bundle</packaging>
    <name>NewsLetter64 - Core</name>
    <description>Core bundle for NewsLetter64</description>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.sling</groupId>
                <artifactId>maven-sling-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <!-- Import any version of javax.inject, to allow running on multiple versions of AEM -->
                        <Import-Package>javax.inject;version=0.0.0,*</Import-Package>
                        <Sling-Model-Packages>
                            com.aem.newsletter.core
                        </Sling-Model-Packages>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- OSGi Dependencies -->
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
      
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-atinject_1.0_spec</artifactId>
        </dependency>
         <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.cmpn</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.annotation</artifactId>
        </dependency>
        <!-- Other Dependencies -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.sling</groupId>
            <artifactId>org.apache.sling.models.api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
        </dependency>
        <dependency>
            <groupId>junit-addons</groupId>
            <artifactId>junit-addons</artifactId>
        </dependency>
    </dependencies>
</project>

Build the OSGi bundle using Maven

To build the OSGi bundle by using Maven, perform these steps:

  1. Open the command prompt and go to the C:\AdobeCQ\NewsLetter64.
  2. Run the following maven command: mvn -PautoInstallPackage install.
  3. The OSGi component can be found in the following folder: C:\AdobeCQ\NewsLetter64\core\target. The file name of the OSGi component is NewsLetter64.core-1.0-SNAPSHOT.jar.

The command -PautoInstallPackage automatically deploys the OSGi bundle to AEM.

View the Active OSGi bundle

After you deploy the OSGi bundle by using the Maven command, you can see it in an active state in the Adobe Apache Felix Web Console.

 

OSGi
The OSGi bundle in an Active State

View your OSGi bundle by performing these steps:

  1. Login to Adobe Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).
  2. Click the Bundles tab, sort the bundle list by Id, and note the Id of the last bundle.

Create an HTL component

Perform these tasks using CRXDE Lite:

1. Right click on /apps/NewsLetter64/components/content and then select New, Component.

2. Enter the following information into the Create Component dialog box:

  • Label: The name of the component to create. Enter newsletter.
  • Title: The title that is assigned to the component. Enter newsletter.
  • Description: The description that is assigned to the template. Enter newsletter.
  • Super Resource Type: Enter foundation/components/parbase.
  • Group: The group in the side rail or side kick where the component appears. Enter NewsLetter64. (The component is located under the NewsLetter64 heading in the Touch UI side rail.)

3. Click Ok.

Once done, you will see the component as shown in the following illustration.

component
The HTL newsletter component

Add a dialog to the HTL component

A dialog lets an author click on the component in the Touch UI (or Classic UI) view during design time and enter values that are used by the component. The component created in this development article lets the AEM author enter information under various tabs.

Dialog
A multi-tab dialog Touch UI dialog

The following illustration shows the JCR nodes for this component. Each dialog is a granite/coral data type. For information about these data types, see Welcome to Granite UI’s documentation.

dialogNodes
JCR Nodes that create the dialog

Note:

Install the package shown at the start of this article to get the JCR nodes that create the Touch UI dialog. This dialog uses a granite/ui/components/coral/foundation/form/multifield granite type. 

Add HTL code

Add code to the HTML file named tab-component located in the following JCR location:

/apps/NewsLetter64/components/content/newsletter/newsletter.html

In the HTL file, notice this line of code (around line 366):

<<!-- 1 Column Text : BEGIN -->
<tr>
<td bgcolor="#008080" class="text-td">
<h2>Current Issue</h2>

<div
data-sly-use.multiItems="com.aem.newsletter.core.models.HeroSlingModel">
<div data-sly-list.head="${multiItems.products.listChildren}">


<p><b>Title:</b> ${head.issueTitle}</p>
<p>URL: <a href="${head.link}" target="_blank">Click HERE</a></p>
<p>${head.issueDesc}</p>
<hr>
</div>
</div>

In this example, notice data-sly-use.multiItems references the Java Sling Model class: com.aem.newsletter.core.models.HeroSlingModel.

The code:

div data-sly-list.head="${multiItems.products.listChildren}">

handles the MultiField.

For each MultiField in the dialog, the following code is executed.

<p><b>Title:</b> ${head.issueTitle}</p>
<p>URL: <a href="${head.link}" target="_blank">Click HERE</a></p> 
<p>${head.issueDesc}</p>

This is how the body of the newsletter is rendered. Add the following HTML to newsletter.html.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta charset="utf-8"> <!-- utf-8 works for most cases -->
	<meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
	<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
    <meta name="x-apple-disable-message-reformatting">  <!-- Disable auto-scale in iOS 10 Mail entirely -->
	<title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->

	<!-- Web Font / @font-face : BEGIN -->
	<!-- NOTE: If web fonts are not required, lines 10 - 27 can be safely removed. -->
	
	<!-- Desktop Outlook chokes on web font references and defaults to Times New Roman, so we force a safe fallback font. -->
	<!--[if mso]>
		<style>
			* {
				font-family: sans-serif !important;
			}
		</style>
	<![endif]-->
	
	<!-- All other clients get the webfont reference; some will render the font and others will silently fail to the fallbacks. More on that here: http://stylecampaign.com/blog/2015/02/webfont-support-in-email/ -->
	<!--[if !mso]><!-->
		<!-- insert web font reference, eg: <link href='https://fonts.googleapis.com/css?family=Roboto:400,700' rel='stylesheet' type='text/css'> -->
	<!--<![endif]-->

	<!-- Web Font / @font-face : END -->
	
	<!-- CSS Reset -->
    <style>

		/* What it does: Remove spaces around the email design added by some email clients. */
		/* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
        html,
        body {
	       margin: 0 auto !important;
            padding: 0 !important;
            height: 100% !important;
            width: 100% !important;
            background-color:#222222 ;
            margin: 0;
            mso-line-height-rule: exactly;
            font-family: adobe-clean, sans-serif; 
        }
        
        /* What it does: Stops email clients resizing small text. */
        * {
            -ms-text-size-adjust: 100%;
            -webkit-text-size-adjust: 100%;
        }
        
        center {	        
            width: 100% !important;
            background-color:#222222 ;            
        }
        
        hr {
            color:#4B4B4B;
            border-width: 1px;
        }
        /* What is does: Centers email on Android 4.4 */
        div[style*="margin: 16px 0"] {
            margin:0 !important;
        }
        
        /* What it does: Stops Outlook from adding extra spacing to tables. */
        table,
        td {
            mso-table-lspace: 0pt !important;
            mso-table-rspace: 0pt !important;
        }
                
        /* What it does: Fixes webkit padding issue. Fix for Yahoo mail table alignment bug. Applies table-layout to the first 2 tables then removes for anything nested deeper. */
        table {
            border-spacing: 0 !important;
            
            table-layout: fixed !important;
            margin: 0 auto !important;
            cellspacing:0; 
            cellpadding:0;
            align:center;             
            margin: auto;
        }
        
        .element{
            width: 600px;
        }
        table table table {
            table-layout: auto; 
        }
        
        /* What it does: Uses a better rendering method when resizing images in IE. */
        img {
            -ms-interpolation-mode:bicubic;
        }
        
        /* What it does: A work-around for iOS meddling in triggered links. */
        .mobile-link--footer a,
        a[x-apple-data-detectors] {
            color:inherit !important;
            text-decoration: underline !important;
        }

        /* What it does: Prevents underlining the button text in Windows 10 */
        .button-link {
            text-decoration: none !important;
        }
      
        /* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89  */
        /* Create one of these media queries for each additional viewport size you'd like to fix */
        /* Thanks to Eric Lepetit @ericlepetitsf) for help troubleshooting */
        @media only screen and (min-device-width: 375px) and (max-device-width: 413px) { /* iPhone 6 and 6+ */
            .email-container {
                min-width: 375px !important;
            }
        }
    
    </style>
    
    <!-- Progressive Enhancements -->
    <style>
        
        /* What it does: Hover styles for buttons */
        .button-td {
            transition: all 100ms ease-in;
            border-radius: 25px; 
            text-align: center;
        }
        
        .button-a {
            transition: all 100ms ease-in;
            background: #009CF9; 
            border: 15px solid #009CF9; 
            font-family: adobe-clean, sans-serif; 
            font-size: 13px; 
            line-height: 1.1; 
            text-align: center; 
            text-decoration: none; 
            display: block; 
            border-radius: 25px; 
            font-weight: bold;
            
        }
        
        .button-tr
        {
            width:auto;
        }
        
        
        
        .button-a:hover {
            background: #009CF9 !important;
            border-color: #009CF9 !important;
            
        }
        
        dd{
            color: #009CF9;
        }
        
        .table-container {
            width:600px;
        }
        
         .image-container {
            
            border:0px ;
            vertical-align: top;
            float:left;
            margin: -90px 0px 0px 90px;
        }
        
        .table-button{
            float:left;
            padding:0px 0px 40px 40px;
        }
        
        .hero-image {
            width:600px; 
            height:300px ;
            border:0px ;
            vertical-align: middle;
            text-align: center; 
            background-position: center !important; 
            background-size: cover !important;
        }
        
        .image-text{
            vertical-align: middle;
            text-align: left; 
            padding: 20px 0px 20px 120px; 
            font-family: adobe-clean, sans-serif; 
            font-size: 15px; 
            line-height: 20px; 
            color: #ffffff;
            background-color: black;
            opacity: 0.6;
            filter: alpha(opacity=60); /* For IE8 and earlier */
            float: left;
            width: 60%;            
        }
        
        .newsedition-text {
            color: #ffdd00;
            font-size: 12px;
        }
        
         .text-right{
            float:right;
        }
        
        .text-td{
            padding: 40px; 
            text-align: left; 
            font-family: adobe-clean, sans-serif; 
            font-size: 15px; 
            line-height: 20px; 
            color: #000000;"
        }
        
        .footer-td{
            padding: 10px 10px 10px 40px;
            width: 100%;
            font-size: 12px; 
            font-family: adobe-clean, sans-serif; 
            line-height:18px; 
            color: #999999;
            background-color: #000000;
        }

        /* Media Queries */
        @media screen and (max-width: 600px) {

            .email-container {
                width: 100% !important;
                margin: auto !important;
            }

            /* What it does: Forces elements to resize to the full width of their container. Useful for resizing images beyond their max-width. */
            .fluid {
                max-width: 100% !important;
                height: auto !important;
                margin-left: auto !important;
                margin-right: auto !important;
            }

            /* What it does: Forces table cells into full-width rows. */
            .stack-column,
            .stack-column-center {
                display: block !important;
                width: 100% !important;
                max-width: 100% !important;
                direction: ltr !important;
            }
            /* And center justify these ones. */
            .stack-column-center {
                text-align: center !important;
            }
        
            /* What it does: Generic utility class for centering. Useful for images, buttons, and nested tables. */
            .center-on-narrow {
                text-align: center !important;
                display: block !important;
                margin-left: auto !important;
                margin-right: auto !important;
                float: none !important;
            }
            table.center-on-narrow {
                display: inline-block !important;
            }

                           
        }

    </style>
    <script>
    	function setIframeHeight(id) {
          var ifrm = parent.document.getElementById(id);
          if (ifrm) {
           var doc = ifrm.contentDocument ? ifrm.contentDocument :
            ifrm.contentWindow.document;
           ifrm.style.visibility = 'hidden';
           ifrm.style.height = "10px"; // reset to minimal height ...
           // IE opt. for bing/msn needs a bit added or scrollbar appears - changed 4 px addition to 10 px due to author instance
           ifrm.style.height = getDocHeight(doc) + "px";
           ifrm.style.visibility = 'visible';
          }
         }
        
        function getDocHeight(doc) {
          doc = doc || document;
          // stackoverflow.com/questions/1145850/
          var body = doc.body,
           html = doc.documentElement;
          var height = Math.max(body.scrollHeight, body.offsetHeight,
           html.clientHeight, html.scrollHeight, html.offsetHeight);
          return height;
         }

    </script>

</head>
<body onload='setIframeHeight("ContentFrame")'>
    <center>

        <!-- Visually Hidden Preheader Text : BEGIN -->
        <div style="display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;mso-hide:all;font-family: sans-serif;">
            (Optional) This text will appear in the inbox preview, but not the email body.
        </div>
        <!-- Visually Hidden Preheader Text : END -->

        
        <!-- Email Body : BEGIN -->
        <table role="presentation" class="email-container table-container">
            
            <!-- Hero Image, Flush : BEGIN -->
          
            
            <tr>
				<td background="https://helpx.adobe.com/content/dam/Adobe/newsletter/newsheader.jpg" alt="alt_text" class="fluid hero-image" > 
                 
                                    <img class="image-container" src="https://helpx.adobe.com/content/dam/help/images/en/adobe.png" width="50" height="80" alt="alt_text" >

                               
                        
                <!--[if gte mso 9]>
                    <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:600px;height:175px; background-position: center center !important;">
                    <v:fill type="tile" src="http://placehold.it/600x230/222222/666666" color="#222222" />
                    <v:textbox inset="0,0,0,0">
                    <![endif]-->
                    <div>
                        <table role="presentation" class="table-container">
                            <tr>
                                <td class="image-text">
                                    <h1> ${properties.imagetitle @ context="html"}</h1>
                                    ${properties.imagedesc @ context="html"}
                                    <div class ="newsedition-text" >${properties.newsedition @ context="html"}</div>
                                   
                                </td>
                            </tr>
                        </table>
                        </div>
                    <!--[if gte mso 9]>
                    </v:textbox>
                    </v:rect>
                    <![endif]-->

				</td>
            </tr>
            <!-- Hero Image, Flush : END -->
            
            

            <!-- 1 Column Text : BEGIN -->
            <tr>
                <td bgcolor="#ffffff" class="text-td">
                     ${properties.text @ context="html"}
                    <br><br>
                    
                </td>
            </tr>
            <!-- 1 Column Text : BEGIN -->
            
              <!-- 1 Column Text : BEGIN -->
            <tr>
                <td bgcolor="#008080" class="text-td">
                    <h2>Current Issue</h2>
                    
					<div
    data-sly-use.multiItems="com.aem.newsletter.core.models.HeroSlingModel">
    <div data-sly-list.head="${multiItems.products.listChildren}">
  
  
        	<p><b>Title:</b> ${head.issueTitle}</p>
          	<p>URL: <a href="${head.link}" target="_blank">Click HERE</a></p>  
            <p>${head.issueDesc}</p>
       	   <hr>
   </div>
</div>



                </td>
            </tr>
            <!-- 1 Column Text : BEGIN -->

                      


            <!-- 1 Column Text + Button : BEGIN
            <tr>
                <td bgcolor="#0C3F5A">
                    <table role="presentation" >
                    	<tr>
                            <td class="text-td">
                                Maecenas sed ante pellentesque, posuere leo id, eleifend dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent laoreet malesuada cursus. Maecenas scelerisque congue eros eu posuere. Praesent in felis ut velit pretium lobortis rhoncus ut&nbsp;erat.
                            </td>
							</tr>  -->
                        
                    <!-- Button : Begin
                    <table role="presentation" class="center-on-narrow table-button"  >
                        <tr>
                            <td class="button-td">
                                <a href="http://www.google.com" class="button-a">
                                   <span style="color:#ffffff;">Subscribe Now</span>
                                </a>
                            </td>
                        </tr>
                    </table> -->
                    <!-- Button : END -->
                <!--   </td>
            </tr>
          1 Column Text + Button : BEGIN -->
            
              <!-- 1 Column Text : BEGIN -->
            <tr>
                <td bgcolor="#ffffff" >
                    <table role="presentation" class="table-container" >
                    	<tr>
                            <td  class="text-td">
                               <h2>Newsletter Issue Archive</h2>
                                 <div data-sly-use.nabeanObj="com.aem.newsletter.core.NewsArchiveMultiBean">
                                    <p>
                                        <div data-sly-test="${!nabeanObj.lnBean}">This is the first edition</div>
                                        <div data-sly-test="${nabeanObj.lnBean}" data-sly-list.items="${nabeanObj.lnBean}">
                                                ${items.pageTitle}
                                            <div class="text-right"><a href="${items.path}" > View Online </a>  </div>                                              
                                             <hr>
                                        </div>
                                    </p>
                                </div>      

                            </td>
							</tr>
                        
                    </table>                    
                </td>
            </tr>
            <!-- 1 Column Text : BEGIN -->

        </table>
        <!-- Email Body : END -->
          
        <!-- Email Footer : BEGIN -->
        <table role="presentation" class="email-container table-container">


			<tr>

                <td class="footer-td">
                        Subscribe to this newsletter by clicking <a href="http://www.form-it.net/FormIT22/778bec8b-650c-44f2-9138-df94caf16c32/ViewFormit.do">Subscribe</a> .
                </td>
            </tr>
            <tr>


            <tr>

                <td class="footer-td">
                        Submit topic ideas by clicking <a href="http://bit.ly/2kMTRYa">Submit Ideas</a> .
                </td>
            </tr>
            <tr>

                <td class="footer-td">
                        Copyright 2019 Adobe System Incorported. All rights reserved.
                </td>
            </tr>
        </table>
        <!-- Email Footer : END -->

    </center>
</body>
</html>

In this example, the image is hard-coded into the HTML. You can set it to read the image that an AEM author dropped into the dialog as opposed to keeping the image static.

Note:

Notice a Script tag contains a method named setIframeHeight. This method is responsible to ensure all of the HTL component is visible in the Touch UI during edit mode. Otherwise, not all of the HTL component is visible.

Create a page based on the news template

The final task that you perform in order to see a web page that renders the newsletter and based on the news template (the template created earlier in this development article).

newsletter

You can view the newsletter page by accessing this URL. 

http://localhost:4502/editor.html/content/NewsLetter64/en.html

Once there, drop the newsletter component into the page, and set the dailog values as shown in this video. 


See also

Join the AEM community at: Adobe Experience Manager Community

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy