Sightly was introduced by AEM 6.0 to replace JSP by a new HTML Templating System. This post is a quick reference about Sightly. A list of best practices and things to know.
Java class or server side Javascript
With Sightly, you can create a component with two methods. By using Java Class or Javascript Server-Side File. Personnaly, I always use Java Class, but Javascript seems to be a really good deal if you want to develop your components with one language. But keep in mind that AEM Java API offer more functionnalities than Javascript API.
- Sigthly component with Java
package apps.mycomponent; import com.adobe.cq.sightly.WCMUse; public class MyComponent extends WCMUse { private String title; private String description; @Override public void activate() throws Exception { title = getProperties().get("title", ""); description = getProperties().get("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; } }
- Sigthly HTML code
<div id="my-component" data-sly-use.cpt="apps.mycomponent.MyComponent"> <!-- /* Here you call the Java Method */ --> <!-- /* Explanation : Imported Class + '.' + Uncapitalized java method name withoud 'get' */ --> <h1>${cpt.title}</h1> <p>${cpt.description}</p> </div>
- Sightly Component with server side Javascript
use(function () { var title = currentPage.getTitle(); var description = properties.get("jcr:description", "default desc"); return { title: title, description: description }; });
You do have to know that you cannot pass argument to the method. But it is possible to pass argument at the activation of the Java/Javascript class. Example with Java Class :
package apps.mycomponent; import com.adobe.cq.sightly.WCMUse; public class MyComponent extends WCMUse { private String title; private String description; @Override public void activate() throws Exception { title = get("title", String.class); } public String getTitle() { return title; } }
Example HTML code
<div id="my-component" data-sly-use.cpt="apps.mycomponent.MyComponent @ title='my title'"> <h1>${cpt.title}</h1> <p>${cpt.description}</p> </div>
Context Objects
With Sightly you can directly use component/page properties in HTML file like JSP does. You can access to a wide range of Java Objects (currentPage, currentNode….) too :
Variable Name | Description |
---|---|
properties | List of properties of the current Resource. |
pageProperties | List of page properties of the current Page. |
inheritedPageProperties | List of inherited page properties of the current Page. |
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 |
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.day.cq.wcm.api.WCMMode (in Sightly, evaluates to a string, either“EDIT” or“DESIGN”) |
xssAPI | com.adobe.granite.xss.impl.XSSAPImpl |
All these objects are accessible using Sightly, server side Javascript and Java class.
Examples:<!-- /* Access to simple component property defined in dialog.xml */ --> ${properties.my_property} <!-- /* Access to JCR property */ --> ${properties.jcr:title} <!-- /* Access to page property */ --> ${pageProperties.name} <!-- /* Access to inherited page property */ --> ${inheritedPageProperties.inherited_property} <!-- /* Visualize all accessible properties */ --> ${properties}
If you want to modify the value before accessing a property you can obviously use a Java Class/Server side Javascript as shown in the first part.
Conditional operators
With sightly you can use conditional operators :
${properties.jcr:title || properties.my_title}
${properties.my_title ? properties.my_title : properties.jcr:title}
You should mix conditional operators and data-sly-test block statement.
<!-- /* If/Else exemples */ -->
<p data-sly-test="${properties.my_property}">Ok</p>
<p data-sly-test="${!properties.my_property}">Ko</p>
<p data-sly-test="${properties.article_number < 5}">Number < 5</p>
<p data-sly-test="${properties.article_number == 5}">Number = 5</p>
<p data-sly-test="${properties.article_number > 5}">Number > 5</p>
String Formatting
<span>${'Hello {0} {1}' @ format=[properties.civility, properties.name]}</span>
I18n / Internationalization
<!-- /* Translates the 'Welcome' string to the language of the current page */ -->
<p>${'Welcome' @ i18n}</p>
<!-- /* Translates the 'Welcome' string to a specify language (french in our case) */ -->
<p>${'Welcome' @ i18n, locale='fr'}</p>
<!-- /* You can mix string formatting and internationalization */ -->
<p>${'Welcome {0} {1}' @ i18n, locale='fr', format=[civility, name]}</p>
Display Context
If you want to write a resource property as an HTML attribute or as an JS comment, the display context is different. That’s why sightly provides some context which will format/filter the property value.
HTML context:
Context Name | When to use | What it does |
---|---|---|
text | Default for content inside elements | Encodes all HTML special characters. |
html | To safely output markup | Filters HTML to meet the AntiSamy policy rules, removing what doesn’t match the rules. |
attribute | Default for attribute values | Encodes all HTML special characters. |
uri | To display links and paths Default for href and src attribute values | Validates URI for writing as an href orsrc attribute value, outputs nothing if validation fails. |
number | To display numbers | Validates URI for containing an integer, outputs zero if validation fails. |
attributeName | Default for data-sly-attribute when setting attribute names | Validates the attribute name, outputs nothing if validation fails. |
elementName | Default for data-sly-element | Validates the element name, outputs nothing if validation fails. |
Javascript context:
Context | When to use | What it does |
---|---|---|
scriptToken | For JS identifiers, literal numbers, or literal strings | Validates the JavaScript token, outputs nothing if validation fails. |
scriptString | Within JS strings | Encodes characters that would break out of the string. |
scriptComment | Within JS comments | Validates the JavaScript comment, outputs nothing if validation fails. |
CSS context:
Context | When to use | What it does |
---|---|---|
styleToken | For CSS identifiers, numbers, dimensions, strings, hex colours or functions. | Validates the CSS token, outputs nothing if validation fails. |
styleString | Within CSS strings | Encodes characters that would break out of the string. |
styleComment | Within CSS comments | Validates the CSS comment, outputs nothing if validation fails. |
Other context :
Context | When to use | What it does |
---|---|---|
unsafe | Only if none of the above does the job | Disables escaping and XSS protection completely. |
Display context can be used as below
<!-- /* write html text in a div */ -->
<div>${properties.wysiwygText @ context='html'}</div>
<!-- /* write style token */ -->
<span style="color: ${properties.color @ context='styleToken'};">Welcome</span>
<!-- /* possible but BAD IDEA (I think...) ! */ -->
<div>${script @ context='unsafe'}</div>
Block statement
data-sly-use : Initializes a helper object (defined in JavaScript or Java) and exposes it through a variable
<!-- /* java class */ -->
<div id="my-component" data-sly-use.cpt="apps.mycomponent.MyComponent">
<h1>${cpt.title}</h1>
<p>${cpt.description}</p>
</div>
<!-- /* js class */ -->
<div id="my-component" data-sly-use.cpt="cpt.js">
<h1>${cpt.title}</h1>
<p>${cpt.description}</p>
</div>
data-sly-unwrap : Removes the host HTML element.
<!-- /* This */ -->
<p data-sly-unwrap>Hello World</p>
<!-- /* Produces */ -->
Hello World
data-sly-attribute : Adds HTML attributes to the host element.
<!-- /* This */ -->
<div data-sly-attribute.class="${properties.myClass}"></div>
<!-- /* Produces */ -->
<div class="colorRed"></div>
With a map of attributes
attributes = {
title: "beautiful title",
class: "testClass",
}
<!-- /* This */ -->
<div data-sly-attribute="${attributes}"></div>
<!-- /* Produces */ -->
<div title="beautiful title" class="testClass"></div>
data-sly-test : Conditionally removes the HTML host element.
<p data-sly-test="${properties.my_property}">Ok</p>
<p data-sly-test="${!properties.my_property}">Ko</p>
data-sly-list : Repeats the content of the host element for each enumerable property in the provided object.
<ul data-sly-list="${properties}">
<li>index: ${itemList.index}</li>
<li>value: ${item}</li>
</ul>
ItemList is an object that is available in the data-sly-list statement and provide the following properties :
- index : counter (0-n)
- count : counter (1-n)
- first : if the current item is the first item
- middle: if the current item is neither the first nor the last item
- last: if the current item is the last item
- odd: if index is odd
- even: if index is even
data-sly-resource : Includes the indicated resource.
<!-- /* Include the component image */ !-->
<div data-sly-resource="${'image' @ resourceType='wcm/foundation/components/image'}"></div>
data-sly-template / data-sly-call : Defines a template and call it.
<!-- /* Define the template */ -->
<template data-sly-template.titleTemplate="${ @ title}">
<h1>${title}
</template>
<!-- /* Call the template */ -->
<div data-sly-call="${titleTemplate@ title='title test'}" data-sly-unwrap></div>
You can define your template in a different file :
<!-- /* Define the template in template.html */ -->
<template data-sly-template.title="${ @ title}">
<h1>${title}
</template>
<!-- /* Call it in index.html /* -->
<div data-sly-use.template="template.html">
<div data-sly-call="${template.title @ title='testTitle'}"></div>
</div>
Clientlibs:
<!--/* Do not forget the data-sly-use ! */-->
<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}">
<meta data-sly-call="${clientLib.css @ categories='myClientlib1'}" data-sly-unwrap/>></meta>
<meta data-sly-call="${clientLib.js @ categories='myClientlib2'}" data-sly-unwrap/>></meta>
<meta data-sly-call="${clientLib.all @ categories=['myClientlib1', 'myClientlib2']}" data-sly-unwrap/>></meta>
</div
No comments :
Post a Comment