Sightly | HTL(HTML Template Language)

HTL (Previously known as Sightly) was first introduced in AEM 6.0 as an alternate of JSP, EcmaScript & JSLT.
Now it is preferred templating language in AEM. It is recommended for new AEM projects to use HTL as it offers multiple benefits compared to JSP. 
Although languages like of JSP (Java Server pages) and ESP (ECMA Script Server Pages) serve well for website development in AEM, HTL is emerging to be a preferred templating language for HTML because, HTML developers can participate better in AEM project without any JAVA knowledge.

Advantages of using HTL:-

·  New AEM developers have shorter learning curve
·  Easy to maintain project with cleaner code
·  Elimination of UI/AEM integration issues
·  Increased developer productivity
·  Secure: URL Externalization and XSS Protection
·  Finally helps you forget about JSP Scriptlets, with embedded business logic.
·  Offers pure view and help move the business logic to Java classes (externalizing the business logic)
·  Addresses problems in AEM such as lack of separation of concerns
·  HTL only Supports HTML5.
·  Using HTL components development becomes a part of Web Developer instead of a java developer.
·  Wider range of implicit objects as compared to JSP.

HTL shows its significance in enabling Java developers to focus on the backend code independently. This specific feature distinguishes HTL from other templating systems where Java developers should have little front-end knowledge for integration. Therefore, HTL often reduces coordination issues, as the frontend development might not be a primary skill for every Java developer.

Features of HTL listed here:

Secure:- The HTL increases the security of sites that use it in their implementation, as compared to JSP and to most other template systems, because HTL is capable of automatically applying the proper context-aware escaping to all variables being output to the presentation layer. HTL makes this possible because it understands the HTML syntax, and uses that knowledge to adjust the required escaping for expressions, based on their position in the markup.
Eg.
<p style="${colorText? 'color:red' : 'color:grey'}">${text}</p>

Looks pretty nice, but doesn’t work, as HTL recognizes the CSS style and removes it as potentially harmful content. Add the context like this, saying ‘I actually want to deliver style information here’:

<p style="${ colorText? 'color:red' : 'color:grey' @ context='styleToken'}">${text}</p>
Separation of concerns:- Separation of concerns defines the separation of the frontend from the business logic in different files. Initially, business would require writing all templates in JSTL, because JSP logic tends to sneak into the views. Another disadvantage is, JSTL can become rather unwieldy and produce lots of clutter. This was very much reduced in HTL and it helps bridge the gap between back end as well as front end development. In JSP you mix markup with Java code using scriptlet but in HTL it’s purely mark up and Java code resides in bundles

Reduced Costs - Increased security, simplified development and improved team collaboration, translates for AEM projects in reduced effort, faster time to market (TTM), and lower total cost of ownership (TCO).


                    
Integrations with sling models:-
HTL does not require Sling models, there are different ways to get your logic into HTL. Still, the sling models are considered as the perfect way to set the Java logic up.
Templates-Define reusable:-
In HTL, Templates tend to define re-usable and potentially recursive methods that can be defined locally or in separate files.
Localizing Terms:-
HTL localize terms provided in dictionaries in an easy and beautiful manner by just adding the context i18n.

Simplified Development: - The HTML Template Language is easy to learn and its features are purposely limited to ensure that it stays simple and straight-forward.
In conclusion, HTL templating engine is a powerful, versatile tool with many benefits for web development in AEM platforms. Additionally, it improves time-to market and reduces the Total Cost of Ownership of Your AEM 6.x projects.  It also helps in introducing a clean separation of concerns and prevents developers from writing business logic and the markup, thus reduces the load time of the webpage.


Difference between Sightly and JSP:-

Sightly Offers below advantages over JSP for better development in AEM
  • Protection against cross-side scripting injection.
  • Easily development of AEM Projects by front-end developers.
  • Flexible and powerful templating and logic binding features
  • Need to write less code in Sightly thus productivity increases.
  • Wider range of implicit objects as compared to JSP.

HTL Block Statements:- 


1:- data-sly-use statement:- 

Initializes a helper object (defined in JavaScript or Java) and exposes it through a variable.

1: HTL Component with Java:-
Initialize a Java class, where the source file is located in the same directory as the template. Note that the classname must be used, not the file name:
<div data-sly-use.nav="Navigation">${nav.foo}</div>
Initialize a Java class, where that class is installed as part of an OSGi bundle. Note that its fully-qualified class name must be used:
<div data-sly-use.nav="org.example.Navigation">${nav.foo}</div>

<div id="my-component" data-sly-use.mycomponent="com.test.wcm.view.helper.MyComponentViewHelper">
    <h1>${mycomponent.title}</h1>
    <p>${mycomponent.description}</p>
</div>

·  Java File (Can be put inside component or can be part of bundle):

package com.test.wcm.view.helper;

import com.adobe.cq.sightly.WCMUsePojo;

public class MyComponentViewHelper extends WCMUsePojo {
       private String title;
       private String description;

       @Override
       public void activate() throws Exception {
              title = getProperties().get("title", "DEFAULT_TITLE");
              description = getProperties().get("description", "DEFAULT_DESCRIPTION");
       }

       // Must have to get back the value in html file
       // Explanation : 'get' + capitalize method name
       public String getTitle() {
              return title;
       }

       public String getDescription() {
              return description;
       }
}

2: HTL Component with server side JavaScript:-
Initialize a JavaScript object, where the source file is located in the same directory as the template. Note that the filename must be used:
<div data-sly-use.nav="navigation.js">${nav.foo}</div>
·  Server Side Java script file(mycomponent.js file in your component folder):-


use(function () {
    var title = currentPage.getTitle();
    var description = properties.get("jcr:description", "default desc");
 
    return {
        title: title,
        description: description
    };
});

·  HTML File:-
<div id="my-component" data-sly-use.mycomponent="mycomponent.js">
    <h1>${mycomponent.title}</h1>
    <p>${mycomponent.description}</p>
</div>


We can Java Class or Javascript Server-Side File. Mostly we use Java Class as  AEM Java API offer more functionalities than Javascript API.



data-sly-unwrap statement:-

Removes the host HTML element while retaining its content.

Example:

<div data-sly-unwrap>Hello World</div>

Output: Hello World


It is also possible to conditionally unwrap an element:

<div class="popup" data-sly-unwrap="${isPopup}">content</div>

sly element:-

<sly> element does not get displayed in the resulting HTML and can be used instead of the data-sly-unwrap. The goal of the <sly> element is to make it more obvious that the element is not outputted. If you want you can still use data-sly-unwrap.
<sly data-sly-test.varone="${properties.yourProp}"/>

data-sly-test statement:-

Test a statement and if condition is false then removes the element and its contents.

Example:
 <p data-sly-test="${properties.isValid}">This is valid</p>

Output:
<p>This is valid</p>

Explanation:
{properties. isValid } is some statement which evaluates to true. Hence displayed.

The result of a test can be assigned to a variable that can be used later. This is usually used to construct "if else" logic, since there is no explicit else statement:
<p data-sly-test.abc="${a || b || c}">is true</p> <p data-sly-test="${!abc}">or not</p>
The variable, once set, has global scope within the HTL file.
Following are some examples on comparing values:

<div data-sly-test="${properties.jcr:title == 'test'}">TEST</div> <div data-sly-test="${properties.jcr:title != 'test'}">NOT TEST</div> <div data-sly-test="${properties['jcr:title'].length > 3}">Title is longer than 3</div> <div data-sly-test="${properties['jcr:title'].length >= 0}">Title is longer or equal to zero </div> <div data-sly-test="${properties['jcr:title'].length > aemComponent.MAX_LENGTH}"> Title is longer than the limit of ${aemComponent.MAX_LENGTH} </div>

data-sly-list statement:-

Repeats the content of the host element for each enumerable property in the provided object.
Here is a simple loop:
<dl data-sly-list="${currentPage.listChildren}"> <dt>index: ${itemList.index}</dt> <dd>value: ${item.title}</dd> </dl>
The following default variables are available within the scope of the list:
item 
: The current item in the iteration.
itemList 
: Object holding the following properties:
index 
: zero-based counter ( 
0..length-1 
).
count 
: one-based counter ( 
1..length 
).
first 
true 
if the current item is the first item.
middle 
true 
if the current item is neither the first nor the last item.
last 
true 
if the current item is the last item.
odd 
true 
if 
index 
is odd.
even 
true 
if 
index 
is even.
Defining an identifier on the 
data-sly-list 
statement allows you to rename the 
itemList 
and 
item 
variables. 
item 
will become *** 
<variable> 
*** and 
itemList 
will become 
*<variable>*List 
.
<dl data-sly-list.child="${currentPage.listChildren}"> <dt>index: ${childList.index}</dt> <dd>value: ${child.title}</dd> </dl>
You can also access properties dynamically:

<dl data-sly-list.child="${myObj}"> <dt>key: ${child}</dt> <dd>value: ${myObj[child]}</dd> </dl>


data-sly-repeat statement:-
This tag helps to repeat an element multiple times based on the list which is specified.
<div data-sly-repeat="${currentPage.listChildren}">${item.name}</div>
The difference with <data-sly-list/> is that list needs a container element where repeat does not require it. 
data-sly-repeat repeats the whole element that is marked, while data-sly-list only repeats the content of the element.

data-sly-resource statement:-
Includes the indicated resource.

Example:1
<sly data-sly-resource="path/to/resource"></sly>

Output: 
<sly><!-- Result of the rendered resource --></sly>
Example:2
<!-- /* Include the component image */ !-->
<div data-sly-resource="${'image' @ resourceType='wcm/foundation/components/image'}"></div>

1: Resource Statement Options
You can specify, add or remove selectors like the following.
Example: 
<article data-sly-resource="${'path/to/resource' @
selectors='mobile'}"></article>

2: Overriding the resourceType

<article data-sly-resource="${'path/to/resource' @
resourceType='my/resource/type'}"></article>

3: Changing the WCM mode on the fly as required: 

<article data-sly-resource="${'path/to/resource' @
wcmmode='disabled'}"></article>

****Include Statement(data-sly-include)****
Includes the rendering of the indicated template (Sightly, JSP, ESP, etc.) 
Example:

<section data-sly-include="path/to/template.html"></section>

Output:

<section><!-- Result of the rendered resource --></section>

***Attribute Statement (data-sly-attribute)***

Adds HTML attributes to the host element.
Example:1
<div data-sly-attribute.class="${properties.myClass}"></div>
Output:
<div class="colorRed"></div>

Example:2 With a map of attributes
attributes = {
    title: "beautiful title",
    class: "testClass",
}
<div data-sly-attribute="${attributes}"></div>

Output:
<div title="beautiful title" class="testClass"></div>

***Template & Call Statement(data-sly-template & data-sly-call)***

These are the HTML blocks which act a function. Every blocks will have an identifier and like normal function they do accept parameters. When you are defining the block, you can define all parameters that will be accepted by it..

Example of template:

File: template.html 
 <template data-sly-template.testUtility="${@ name, title}">
<span class="${name}">${title}</span>
</template>

So as we can see the above template.html gets defined similar to a method/function in JAVA.

File: Caller.html 
<div data-sly-use.tmpl="template.html"
data-sly-call="${tmpl.testUtility@ name='Saurabh',
title='Kumar'}"></div>

Ouput:
<div><span class="Saurabh">Kumar</span></div>


In short the Template Statement is used to define a method/function.
The Call Statement is used to call the defined method.

How to add client library on page in HTL:
!--/* Do not forget the data-sly-use ! */-->
<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}">
 <div data-sly-call="${clientLib.css @ categories='comp1'}" data-sly-unwrap/></div>
 <div data-sly-call="${clientLib.js @ categories='comp12'}" data-sly-unwrap/></div>
 <div data-sly-call="${clientLib.all @ categories=['comp1', 'comp2']}" data-sly-unwrap/></div>
</div>


What are the implicit object present in sightly?

HTL provides access to all objects that were commonly available in JSP after including 
global.jsp

Enumerable Objects

These objects provide convenient access to commonly used information. Their content can be accessed with the dot notation, and they can be iterated-through using 
data-sly-list or  data-sly-repeat 
.

Java-backed Objects

Each of the following objects is backed by the corresponding Java object.
The most useful variables in the table below are highlighted in bold.


Variable Name
Description

component

com.day.cq.wcm.api.components.Component

componentContext

com.day.cq.wcm.api.components.ComponentContext

currentDesign

com.day.cq.wcm.api.designer.Design

currentNode

javax.jcr.Node

currentPage

com.day.cq.wcm.api.Page

currentSession

javax.servlet.http.HttpSession

currentStyle

com.day.cq.wcm.api.designer.Style

designer

com.day.cq.wcm.api.designer.Designer

editContext

com.day.cq.wcm.api.components.EditContext

log

org.slf4j.Logger

out

java.io.PrintWriter

pageManager

com.day.cq.wcm.api.PageManager

reader

java.io.BufferedReader

request

org.apache.sling.api.SlingHttpServletRequest

resolver

org.apache.sling.api.resource.ResourceResolver

resource

org.apache.sling.api.resource.Resource

resourceDesign

com.day.cq.wcm.api.designer.Design

resourcePage

com.day.cq.wcm.api.Page

response

org.apache.sling.api.SlingHttpServletResponse

sling

org.apache.sling.api.scripting.SlingScriptHelper

slyWcmHelper

com.adobe.cq.sightly.WCMScriptHelper

wcmmode

com.adobe.cq.sightly.SightlyWCMMode

xssAPI

com.adobe.granite.xss.XSSAPI

Comments

Popular posts from this blog

AEM Scheduler

AEM Sling Servlet

Event Handling in AEM