Thursday, October 12, 2023

Understanding HTL Syntax in AEM | Sightly

Understanding HTL Syntax in AEM

HTL syntax is divided into two main parts: Block Statements and HTL Expressions.





MVC Design Pattern In AEM


HTL Expression: 

As we saw in the top first  Diagram HTL syntax is divided into  block statements and HTL Expression  
HTL expressions display data from variables, arrays, or objects on an HTML/HTL page.





HTL Block Statements

HTL Block Statements control logic and structure within the template.

Logic File

Let's define a logic file logic.js containing our logic, you can define your login in sling modals as you like.




function test(){
std = [
{
name:"Awais",
title : "Engineer",
},
{
name:"Zahid",
title : "Professional",
},
{
name:"Kamran",
title : "Student",
},
];
return {
std: std,
Arr: ["School","College","University"],
page: pageManager.getPage("/content/we-retail/us/en")
}
};

use(test);


HTL Template


<!DOCTYPE html>
<!--/* Calling the server-side JS script for all view logic that Sightly cannot do */-->
<html data-sly-use.logic="logic.js">

<head>
    <!--/* Expressions allow to easily output variables will set the currentPage Title*/-->
    <title>${currentPage.title}</title>
    <meta charset="utf-8">
</head>


<body>


  •    <!--/* Two different ways to show the current Page title first is Block Statement and 2nd is HTL Expression /-->

         <div data-sly-text = "${currentPage.title}"></div>
         <div>${currentPage.title}</div>         

Output

HTL REPL
HTL REPL


  •  <!--/* use to change the value of an attribute: in the bottom example, the value of id will be changed by the value of currentPage.title*/-->

    <div id="working" data-sly-attribute.id = "${currentPage.title}"></div>

            Output

output will not shown on the page but it will update the value of the id with HTL REPL bcoz its current page title



  • <!--/* use to change the value of Element : in following example the h6 will be changed by the h1*/-->

    <h6 data-sly-element="h1">replace Element Value</h6>

      Output

     It will print Replace Element Value in H1 Tag  
   
    




  •    <!--/* following example is showing the child pages of current page repeat is same as  list*/-->
             <div data-sly-repeat="${currentPage.listChildren}">
                    <a href="${item.path}">${item.name}</a>
             </div>

            Output

                us 
                bcoz this  current page having only child page that is US 





  •    <!--/* following example is showing the child pages of the page that you are getting in logic.js file, and begin is telling starting index and end is telling ending index.*/-->
               <div data-sly-list="${logic.page.listChildren @ begin=1 , step=1, end =5}">
                     <li><a href="${item.path}">${item.name}</a></li>
               </div>

        Output

               

 
    
  •    <!--/* Following example is used to iterating the array of object that is defend in logic.js file you can print as well index , count or can check EVEN ODD etc*/-->
     <ul data-sly-list="${logic.std}">
         <li>
          - ${item.name}
          - ${item.title}    
          - (Index : ${itemList.index})  
          - (count : ${itemList.count})
          - (first : ${itemList.first})
          - (middle : ${itemList.middle})
          - (last : ${itemList.last})
          - (Odd : ${itemList.odd})
          - (Even : ${itemList.even})
          </li>
     </ul>

        Output

  • -Awais - Engineer - (Index : 0) - (count : 1) - (first : true) - (middle : false) - (last : false) - (Odd : true) - (Even : false)
  • - Zafar - Professional - (Index : 1) - (count : 2) - (first : false) - (middle : true) - (last : false) - (Odd : false) - (Even : true)
  • - Kamran - Student - (Index : 2) - (count : 3) - (first : false) - (middle : false) - (last : true) - (Odd : true) - (Even : false)




  •  <!--/* Following example we are creating x variable and printing its value*/-->
            <p data-sly-set.x="${5}"></p>
                value : ${x}

            Output

            value : 5



  •  <!--/* working will print when x have value, its mean it will work like if statement*/-->
            <p data-sly-set.x="${12}"></p>
                <p data-sly-test = "${x}">
                    working
                </p>


 

  • <!--/* In following way we use oprators*/-->
            <p data-sly-test = "${false || true}">
                working
            </p>

    </div>       
</body>
</html>




Accessing JSON Output in AEM

Tip: Add .7.json at the end of your AEM page URL to view structured JSON output.

example : http://localhost:4502/editor.html/content/we-retail/us/en/men.html.7.json


Accessing Child Elements



<div data-sly-list.child="${resource.getChildren}">
<div data-sly-list.childItem="${child.getChildren}">


<sly data-sly-test="${childItem.hasChildren}"> // if having children
        if you want to loop the child pages you need to make it again here

<p class="text-success">${childItem.pageLabel}</p>
</sly>
<sly data-sly-test="${!childItem.hasChildren}"> //if not having children
<a href="" class="text-success"> ${childItem.pageLabel} </a>
</sly>
</div>
</div>
SOME CONDITIONAL RENDERING

Directly accessing any properties from 7.json

 ${properties['navigationPages/item0/megaMenu/item2/subPageLabel']}




Conditionally Iterating Over Child Resources in HTL


<div data-sly-list.child="${resource.getChildren}">
<ul data-sly-list.item="${child.name == 'columnTwo' ? child.getChildren : []}">
<li>
<p>${item.label}</p>
<p>${item.link}</p>
</li>
</ul>
</div>


This HTL code iterates over the child resources of the current component using data-sly-list.child="${resource.getChildren}". It then checks if a child has the name "columnTwo", and if so, it retrieves its children using data-sly-list.item="${child.name == 'columnTwo' ? child.getChildren : []}". Each child of "columnTwo" is then displayed in a list, showing its label and link properties. If "columnTwo" does not exist or has no children, nothing is rendered.


Instead of Two Loops, we can get children in one Iteration too.

<div class="tab-content mt-3" id="myTabContent">
<!--*/ All-Tab /*-->
<div class="tab-pane fade show active" id="all" role="tabpanel"
            aria-labelledby="all-tab">
<div data-sly-test="${resource.getChildren[0]}"
           data-sly-list.tabsItems="${resource.getChildren[0].getChildren}" class="row">
<div data-sly-test="${tabsItems.getChildren[0]}"
data-sly-repeat.items="${tabsItems.getChildren[0].getChildren}"
             class="col-lg-4 offer-card-wrap">
<div class="offer-card">
<div>
<img src="${items.cardImage}" alt="offer thumbnail" class="thumbnail" />
<h4 class="title">${items.cardTitle}</h4>
</div>
<div class="details">
<span class="date">
                ${properties.validityLabel} ${'yyyy-MM-dd' @ format=items.date, type='date'}
                 </span>
<a class="link" href="${items.link @ extension = 'html'}">
                    ${properties.learnMoreLabel}</a>
</div>
</div>
</div>
</div>
</div>



Problem Statement (Generalized & Clear)

We have an existing component called faqs that is already used on more than 10 pages in production.

Each page contains different content inside the cici component.

For example:

  • Web-Home → faq (Home content)
  • Web-Service → faq (Service content)
  • Web-Gold → faq (Gold content)

All these pages are already deployed and live in production.


New Requirement

Now we need to create 10 new pages for another section (for example, Mobile pages).

On these new pages:

We created a new component called vivi

This vivi component has a different design/layout

But it must display the same content that already exists inside the corresponding faq component on the Web pages


Solution


<section>
<div>

<h1>${properties.title}</h1>
<h1>${properties.webPage}</h1>

<!-- webPage is the path of the page in which the component is added, we are getting
        this path from cq: dialogue
example: /content/projectName/language-master/en/cards
-->
<sly data-sly-test="${properties.webPage}">
<!-- Page path+ componentPath on the page can get from CRXDLITE from top search-->
<sly data-sly-set.cici="${properties.webPage}/jcr:content/root/container/faqs" />
<sly data-sly-use.ciciPath="${cici}" />


<!-- Using data-sly-use to fetch and display only the content of the
                faq component from webPage -->
<h1>${ciciPath.title}</h1>

<!-- Using data-sly-resource to embed the entire faq component
                 (layout + content) from the webPage page -->
<sly data-sly-resource="${ciciPath @ wcmmode='disabled'}" />

</sly>

</div>
</section>


How to get the component Path on the Page





Click here for : HTL Specifications
Click here for: Global Object

Previous Post
Next Post

post written by:

0 comments: