April 1, 2020
Estimated Post Reading Time ~

How to Sightly in AEM / CQ

Use Case: Some common how to in Sightly

Prerequisite: Please read the following document carefully before some other How-to questions

Sightly Specification: https://github.com/Adobe-Marketing-Cloud/sightly-spec/blob/master/SPECIFICATION.md
Basics of Sightly: https://docs.adobe.com/docs/en/aem/6-1/develop/sightly.html
Sightly tutorials: http://blogs.adobe.com/experiencedelivers/experience-management/sightly-intro-part-1/ (Check other parts on the same page)
Sightly Presentation: http://www.slideshare.net/GabrielWalt/component-development

CodeBase: https://github.com/apache/sling/tree/trunk/bundles/scripting/sightly
Here are some common How to in sightly

How to include ClientLibs in Sightly
<head data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}">

<!--/* for css+js */-->
<meta data-sly-call="${clientLib.all @ categories='your.clientlib'}" data-sly-unwrap></meta>

<!--/* only js */-->
<meta data-sly-call="${clientLib.js @ categories='your.clientlib'}" data-sly-unwrap></meta>

<!--/* only css */-->
<meta data-sly-call="${clientLib.css @ categories='your.clientlib'}" data-sly-unwrap></meta>

</head>


How to Loop fixed number of set in Sightly
#Fixed Array
<ul data-sly-list="${ [1,2,3,4] }">
<li>${item}</li>
</ul>

#List page children
<ul data-sly-list.child="${currentPage.listChildren}">
<li>${child.title}</li>
</ul>


How to create for or while loop in sightly?
You can not have dynamic while loop directly in Sightly scripting. However, you can use Use class to simulate while or for loop in Sightly. Here is an example

#In your Java Class
#this assumes that there is a multi-string property tab

package com.wemblog.use;
public class WemBlogUse extends WCMUse {

/**
* CASE 1: Just access a multi-value property and iterate over them
*/
public Iterator<Map<String, Object>> getTabTitles(){
List<Map<String, Object>> infos = new LinkedList<Map<String,Object>>();
String[] tabTitles = getProperties().get("tabs", String[].class);
if (tabTitles == null || tabTitles.length == 0) {
tabTitles = new String[1];
tabTitles[0] = i18n.get("Tab One from sightly");
Map<String, Object> map = new HashMap<String, Object>();
map.put("tabTitle", tabTitles[0]);
infos.add(map);
}else if(tabTitles.length > 0){
for (String tab : tabTitles) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("tabTitle", tab);
infos.add(map);
}
}
return infos.iterator();
}

/**
* CASE 2:
* Get List of all Column Names. For now, we name them as "column-0...n" based on column number
* @return
*/
public List<String> getAllColumns() {
List<String> allColumns = new ArrayList<String>();
for (int i = 1; i <= Integer.parseInt(getProperties().get("count", "3")); i++) {
allColumns.add("Test" + "-" + i);
}
return allColumns;
}

/**
* CASE 3:
* Example of returning list of Object
* Note that you can just return a model here as well and then access their property in sightly templating language
*/
public List<Page> getBreadCrumbs(){
//Some logic that will return list of page
}

}


# In your Sightly html
<sly data-sly-use.wemBlog="com.wemblog.use.WemBlogUse"></sly>
<sly data-sly-list.mytabTitles="${wemBlog.tabTitles}">
<li>
<ul>${mytabTitles.tabTitle}</ul>
</li>
</sly>

# This will include number of parsys specified by count number above
<sly data-sly-list.eachColumn="${wemBlog.allColumns}">
<section>
<sly data-sly-resource="${ @path=eachColumn, resourceType='foundation/components/parsys'}"></sly>
</section>
</sly>

# SHow Breadcrumb
#Note that since Use class is retuning a page object here, you can perform
# all page operations on that object
<ul data-sly-list="${wemBlog.breadcrumbs}">
<li>${item.properties.navTitle || item.title}</li>
<a href="${item.path}.html">${item.properties.navTitle || item.title}</a>
</li>
</ul>


How to reference another OSGI service in sightly You can not directly reference OSGI service in the sightly template. However, you can reference them in use class using getSlingScriptHelper().getService(Service.class) note that you can not use @Reference to refer a service in sightly class.

How to initialize a default value of a property in sightlyBest way to initialize a value is in activate method of use class. You can also do it in sightly template using something like <sly data-sly-test.parentNavName="${currentPage.properties.navTitle || currentPage.title || currentPage.pageTitle }"> and then use ${parentNavName}

How to access string array in Sightly This is pretty much similar to what we did in for loop. Here is some more generic example

package com.project.sightly;

import com.adobe.cq.sightly.WCMUse;
import org.apache.sling.commons.json.JSONObject;

import java.util.*;

public class JsonHelper extends WCMUse {

private String[] json;

@Override
public void activate() throws Exception {
json = this.get("json", String[].class);
}

public List<Map<String, String>> getValues() {
List<Map<String, String>> results = new ArrayList<Map<String, String>>();

if (json != null) {
for (String value : json) {
Map<String, String> column = parseItem(value);
if (column != null) {
results.add(column);
}
}
}

return results;
}

private Map<String, String> parseItem(String value) {
Map<String, String> columnMap = new HashMap<String, String>();

try {
JSONObject parsed = new JSONObject(value);
for (Iterator<String> iter = parsed.keys(); iter.hasNext();) {
String key = iter.next();
String innerValue = parsed.getString(key);
columnMap.put(key, innerValue);
}

return columnMap;
} catch (Exception e) {

}

return null;
}
}
You can use it like this:

<div data-sly-use.multi="${'com.project.sightly.MultiField' @ json=properties.items}">
<div data-sly-repeat="${multi.values}">
<h2>${item['linkLabel']} - ${item['anchor']}</h2>
</div>
</div>


How to create/access map in sightly Here is one example of how you can do that

package com.test;

import java.util.HashMap;
import java.util.Map;
import com.adobe.cq.sightly.WCMUse;

public class WcmUseSample extends WCMUse {
private Map<String, String> myHashMap;

public void activate() throws Exception {
myHashMap = new HashMap<String, String>();
for (int i = 0; i < 10; ++i) {
myHashMap.put(""+i, "Hello "+i);
}
}
public Map<String,String> getMyHashMap() {
return myHashMap;
}
}

<div data-sly-use.myClass="com.test.WcmUseSample" data-sly-unwrap>
<ul data-sly-list.keyName="${myClass.getMyHashMap}">
<li>KEY: ${keyName}, VALUE: ${myClass.getMyHashMap[keyName]}</li>
</ul>
</div>


How to use the Sling Model with SightlyHere is one example of how you can do it. Note that You can also create a sling model for a resource and then use other use classes to return the sling model.

package wemblog.sightly.use

@Model(adaptables = SlingHttpServletRequest.class)
public class ExternalUrl {

@Inject
private Externalizer externalizer;
@Inject // Using the bindings from Sightly (${currentPage.path}
protected Page currentPage;
@Inject @Optional // parameter from data-sly-use
protected String path;

@PostConstruct
protected void init() {
String relPath = currentPage.getPath();
if ( path != null) { // check if there is a parameter
relPath = path;
}
absoluteUrl = externalize(relPath);
}
protected String externalize(String path) {
return externalizer.absoluteLink(request, "http", path);
}

}



#In your Sighly file
<meta data-sly-use.externalizer="${'wemblog.sightly.use.ExternalUrl' @ path=resourcePage.path}"
property="og:url"
content="${externalizer.absoluteUrl @ context='uri'}.html" />


How to hide element in SightlyYou can use either data-sly-unwrap or <sly> tag for this here is an example

<!--/* This will only show "Foo" (without a <div> around) if the test is true: */--> <div data-sly-test="${myTest}" data-sly-unwrap>Foo</div> <!--/* This would show a <div> around "Foo" only if the test is false: */--> <div data-sly-unwrap="${myTest}">Foo</div>

<!--/* This will display only the output of the 'header' resource, without the wrapping <sly> tag */--> <sly data-sly-resource="./header"></sly>

<sly data-sly-unwrap="${false}"></sly> <!--/* outputs: <sly></sly> */-->



How to pass a sightly object as a parameter in Sightly

#Initialize a variable
<sly data-sly-test.pagePath="${currentPage.path}"/>
<sly data-sly-test.someString='test'/>
<sly data-sly-use.SomeOtherObject="${'TopNavHelperUse' @ test='test'}">

<sly class="sightly-topnav" data-sly-use.topnav="${'Topnav' @ pageNumber='5', someString=someString, pageObject=currentPage, helperString=SomeOtherObject.test}"/>

${topnav.totalPage} ${topnav.someOtherString} ${topnav.pagePath} ${topnav.helperTest}

#Here is Output


15 test and test2 /sometestPath testtest5

#Here is Java Class Example
import com.adobe.cq.sightly.WCMUse;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.day.cq.commons.Filter;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageFilter;

public class Topnav extends WCMUse {
public int getTotalPage(){
return Integer.parseInt(get("pageNumber",String.class))+10;
}

public String getSomeOtherString(){
return get("someString",String.class)+" and test2";
}

public String getPagePath(){
return get("pageObject",Page.class).getPath();
}

public String getHelperTest(){
return get("helperString",String.class) + "test5";
}
}

#Other Class
public class TopNavHelperUse extends WCMUse {
public String getTest(){
return get("test",String.class);
}
}

More use cases to come. Please suggest me any use case you want to get clarity on.

Some more useful Link:
Creating First Sightly Component: https://helpx.adobe.com/experience-manager/using/creating-sightly-component.html
Create an AEM project with Sightly Example: https://github.com/Adobe-Marketing-Cloud/aem-project-archetype
Good Example of Sightly Application using Sling: https://github.com/nateyolles/publick-sling-blog
Sightly To do App: https://github.com/Adobe-Marketing-Cloud/aem-sightly-sample-todomvc
All Available Context and implicit object in JS and JAVA: http://aemtuts.com/aem-sightly-quick-reference/
All Available global Object: https://docs.adobe.com/docs/en/aem/6-0/develop/sightly/global-objects.html



By aem4beginner

No comments:

Post a Comment

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