May 13, 2020
Estimated Post Reading Time ~

Sightly (HTL) in AEM

Sightly is the HTML markup language that Adobe have made to replace the use of jsp in your pages.
I am not going to do a deep dive into sightly, for more documentation go to the sightly documentation page. I will talk about the main attributes of sightly and how they are used.
You have already seen a few of the tags in the examples in the last few pages.
So here are some of the more interesting ones

data-sly-use

This is probably the most heavily used tag in sightly, it allows you to include either another script (js or html), or a model (model or wcmuse)
The main use case is to add the name you want the object known as after data-sly-use. by not putting a name, the object may run but is not usable anywhere else in the html.
We have seen a lot of different variations of the wcm use from
<meta charset="utf-8" data-sly-use.head="head.js">
javascript:
which makes the json structure returned from the head.js available in the head variable
While this is using a WCM javascript file for serverside processing, replacing head.js with the fully qualified name of a java class will get the data from the java class instead.
We have also seen the data-sly-use used to call templates, in this case the templates file for client libs
<sly data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html" data-sly-call="${clientLib.js @ categories='sample.application.site'}" data-sly-unwrap/>
our object /libs/granite/sightly/templates/clientlib.html is called clientLib, we then use the data-sly-call attribute to call a function from, in this case clientLib.js which is a template defined in the html file.
As with the data-sly-call attribute you can pass parameters to the initial object
data-sly-use.item="${'sample.core.models.ItemModel' @data='item'}"
This will pass the parameter to the class, it will be accessible via the get method of WCMUse
String data = get("data" ,String.class);

data-sly-test

This is probably the second heaviest attribute that i use in my applications. It allows you to test values and only allow the element to be added if it returns true
One thing to note that in sightly a null is classed as false when it comes to tests.
<div data-sly-test.editor="${wcmmode.edit || wcmmode.design}">
edit mode
</div>
<div data-sly-test="${!editor}">
not edit mode
</div>
As you can see just like in other sightly tags you can name the response so it can be used in other locations in the html. You can use any object that has been pre-defined by sightly, or a data-sly-use attribute, and this is quite often it's main use case.
<div data-sly-use.obj="sample.core.models.AnObject" data-sly-test="${obj.test}></div>
I use it heavily in components so that i can have an editorial view of the components that potentially give me more information, while then having a non edit mode version for the final display

data-sly-unwrap

Again, heavily used especially with the include tags, it's main purpose is to remove the surrounding tags when processing. So for
<sly data-sly-include="partials/foot/itemlibs.html" data-sly-unwrap/>
Instead of having an html element of sly in the code all that would be there would be the contents of the itemlibs.html. The same goes for adding clientlibs, which will add the script/link tags. If you didn't have data-sly-unwrap then you would have them embedded in a sly tag

data-sly-attribute

The attribute attribute allows you to overwrite an attribute, if the value is empty the original value will remain
<div title="Lorem Ipsum" data-sly-attribute.title="${properties.jcr:title}"></div>
With attributes you can also pass an attribute map to set multiple attributes at the same time. i.e
attrMap = {
title: "myTitle",
class: "myClass",
id: "myId"
}
<div data-sly-attribute="${attrMap}"></div>
Obviously the attrMap would be created using a data-sly-use object

data-sly-element

Just like the attributes you can change the name of the element itself
<h1 data-sly-element="${titleLevel}">text</h1>

data-sly-text

While i don't tend to use data-sly-text much, it has the same purpose as data-sly-attribute, but for the content of the element instead of an attribute
<p data-sly-text="${properties.jcr:description}">Lorem ipsum</p>

data-sly-repeat

Repeats the current element for every item a list
<div data-sly-repeat="${currentPage.listChildren}" data-sly-attribute.class="${item.name}">${item.name}</div>
The default value is called item unless specifically named.

data-sly-list

Similar to the data-sly-repeat attribute, however instead of repeating the current element, it only repeats the elements embedded inside the element
<dl data-sly-list="${currentPage.listChildren}">
<dt>index: ${itemList.index}</dt>
<dd>value: ${item.title}</dd>
</dl>
Again, unless specified the item is called item. lists also add another variable called itemList which gives you more information on the current position in the list. If you add a name for the item i.e data-sly-list.child then the itemList will change as well, in this case to childList

data-sly-resource

The data-sly-resource attribute is generally used to bring in the results or rendering another resource
<article data-sly-resource="${ @ path='path/to/resource'}"></article>
<article data-sly-resource="${'resource' @ prependPath='my/path'}"></article>
<article data-sly-resource="${'my/path' @ appendPath='resource'}"></article>
while i won't go into the details of all of the resource calls, you can add/remove/modify selectors, change the wcmmode that the new resource thinks it is in, or change the decoration tag name surrounding the new component

data-sly-include

Replaces the current element with the contents of the resource
<section data-sly-include=<"path/to/template.html"></section>
You can also include jsp's with the data-sly-include. This also allows the same options for selectors and wcmmode that data-sly-resource provides

data-sly-template and data-sly-call

Both of these attributes are linked together.
While data-sly-template defines a template or set of templates that can be used, data-sly-call tells the template to run.
We see this in the clientLibs examples
We do a data-sly-use of the html /libs/granite/sightly/templates/clientlib.html which contains a couple of templates
<!-- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ ADOBE CONFIDENTIAL
~ __________________
~
~ Copyright 2014 Adobe Systems Incorporated
~ All Rights Reserved.
~
~ NOTICE: All information contained herein is, and remains
~ the property of Adobe Systems Incorporated and its suppliers,
~ if any. The intellectual and technical concepts contained
~ herein are proprietary to Adobe Systems Incorporated and its
~ suppliers and are protected by trade secret or copyright law.
~ Dissemination of this information or reproduction of this material
~ is strictly forbidden unless prior written permission is obtained
~ from Adobe Systems Incorporated.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -->
<!-- /*
Template used for including CSS client libraries
*/ -->
<template data-sly-template.css= "${@ categories='Client Library categories'}" >
<section data-sly-test= "${request.getResourceResolver}"
data-sly-use.clientlib= "${'/libs/granite/sightly/templates/graniteClientLib.html'}"
data-sly-call= "${clientlib.include @ categories=categories, mode='css'}"
data-sly-unwrap>
</section>
</template>
<!-- /*
Template used for including JS client libraries
*/ -->
<template data-sly-template.js= "${@ categories='Client Library categories'}" >
<section data-sly-test= "${request.getResourceResolver}"
data-sly-use.clientlib= "${'/libs/granite/sightly/templates/graniteClientLib.html'}"
data-sly-call= "${clientlib.include @ categories=categories, mode='js'}"
data-sly-unwrap>
</section>
</template>
<!-- /*
Template used for including ALL client libraries
*/ -->
<template data-sly-template.all= "${@ categories='Client Library categories'}" >
<section data-sly-test= "${request.getResourceResolver}"
data-sly-use.clientlib= "${'/libs/granite/sightly/templates/graniteClientLib.html'}"
data-sly-call= "${clientlib.include @ categories=categories}"
data-sly-unwrap>
</section>
</template>
as you can see it defines 3 templates with parameters
when we use it we call which template we want to use
<sly data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html" data-sly-call="${clientLib.js @ categories='sample.application.site'}" data-sly-unwrap/>
In this case, we are calling the template file clientLib so we are then doing a call to the js template in that file with the required parameters.

Expressions

So far we have talked about the attributes that sightly allows you to use to make up the html, the rest of sightly is in its expression language. In general, the expression language exposes the value of an object i.e. ${obj.value} like most scripting languages in Java, you don't have to use get and set as it will be used by default for java objects, or the value for json objects. You can also use array notation ${obj[value]} however I prefer using object notation as it is cleaner.
If you want to create a value to be used in another expression you can create literal values i.e. ${true} ${55} ${'hello'} ${[1,2,3,4]}
While an expression needs to represent a single value, you can use it to create boolean values such as is used in data-sly-test ${1=3}
An expression can have options, the main use case of the options is to send parameters when used in the data-sly-use annotation ${'sample.core.models.Model @ var1=1,var2="2",var3=['1','2','3']}

Special Expressions

There are a couple of special expressions around string handling.
The first is string formatting. ${'Page {0} of {1}' @ format=[current, total]} this allows you to pass parameters to a format that may have been pre-defined, or come from another object.
The second and probably the most important is the internationalisation of the content ${'Page' @ i18n} at its basic instance this will replace Page with the translation based on the defined language for the user, there are many different ways of handling the internationalization, for most of my apps I tend to do use a locale object to define the locale I want the page translated into for the user ${linkModel.title @i18n, locale=userlocale.locale}


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.