Featured

Saturday 30 April 2016

How to use data-sly attributes in slghtly with AEM

Here we will discuss some scenarios which are related to using the data-sly attributes to specific HTML-elements.
We can use all the data-sly attributes everywhere you like.
These scenarios will explain, data-sly-list with HTML5 article and section tags

Scenrio-1:  
            <article data-sly-list="${currentPage.listChildren}">
  <section>
    <h1>${item.title}</h1>
    <h2>${item.properties.subtitle}</h2>
    <h3 data-sly-test="${item.listChildren}">My page has subpages</h3>
  </section>
</article>
 
Preserve the markup from the designer
How many times do you get a HTML snippet from a designer with some nice mock data in there? And what do we with that?, we rip it apart and you just end up with a small snippet and you lost the context of it.
Now with sightly you can preserve the markup including the mock data, and still make it fully functional.
In the scenario below I have received a navigation HTML snippet, and integrated this with sightly. Via the empty data-sly-test attributes the elements are suppressed completely.

Scenrio-2:
<ul data-sly-list="${currentPage.listChildren}">
  <li data-sly-text="${item.title}">This is the first menu item from my page</li>
  <li data-sly-test><a href="#">This is the second menu item from my page </a></li>
  <li data-sly-test><a href="#">This is the third menu item from my page </a></li>
  <li data-sly-test><a href="#">This is the fourth menu item from my page </a></li>
</ul>
 
Naming your data-sly-test expression:
With data-sly-test you can show or hide an HTML element.
What you also can do is to name your expression and reuse that in other data-sly-test expression.
In the scenario below I have data-sly-test-valid, that then can used as ‘valid’ in the other data-sly-test expression.

Scenrio-3:
<div data-sly-test.valid="${pageProperties.name}">${pageProperties.name}</div>
<div data-sly-test="${!valid && wcmmode.edit}">Please enter a name for this page</div>
Hiding container elements
If some cases you have a need to hide a container element, for example hiding the <ul> for a list, or not generating a surrounding <div>
For these cases you can use the data-sly-unwrap attribute.
In this example we generate a list of <li> items, without the <ul>.

Scenrio-4:
<ul data-sly-list.child="${currentPage.listChildren}" data-sly-unwrap>
  <li>${child.title}</li>
</ul>
You can also pass an expression to the data-sly-unwrapped attribute to make it conditional.
Here you see that only in edit-mode the <ul> is hidden.

Scenrio-5:
<ul data-sly-list-child="${currentPage.listChildren}" data-sly-unwrap="${wcmmode.edit}">
  <li>${child.title}</li>
</ul>
Custom Java-classes
In most projects you will find yourself in need to write some custom code to support your components. With sightly you can use the data-sly-use attribute for that.

Scenrio-6:
<div data-sly-use.comp1="com.myproject.SightlyComponent">
  <h1>${comp1.myTitle}</h1>
</div>
Java-class, option 1
We have a few options how you can write your custom class, the first option is that your Java-class is extending the “WCMUse” class from Sightly.
When extending this class you are able to call methods like “getResource()”, “getCurrentPage()”, “getPageManager()” etc.
Here an example of a Java-class that extends WCMUse.
SightlyComponent.java
                  public class SightlyComponent extends WCMUse  {
  private String myTitle;
  @Override
  public void activate() {
    myTitle = "My Project " + getCurrentPage().getTitle();
  }
  public String getMyTitle() {
    return myTitle;
  }
}
Java-class, option 2
If you don’t feel comfortable to extend a class, you can also implement the Use-interface.
Via the init() method you can access all the bindings that are available. These are things like “currentPage”, “resource”, “request” etc.
Here an example of this implementation.
SightlyComponent.java
                  public class SightlyComponent implements Use {
  private String myTitle;
  @Override
  public void init(Bindings bindings) {
    Page currentPage = (Page) bindings.get(WCMBindings.CURRENT_PAGE);
    myTitle = currentPage.getTitle() + "new";
  }
  public String getMyTitle() {
    return myTitle;
  }
}
We have some more options how you can implement Java-classes, but I will cover that in a next article.
In this final example you can see how you can access a service from the WCMuse-class
SightlyComponent.java
                  public class SightlyComponent extends WCMUse  {
  private String myTitle;
  @Override
  public void activate() {
    myTitle = "My Project " + getCurrentPage().getTitle();
    MyService service = getSlingScriptHelper().getService(MyService.class);
    service.action(myTitle);
  }
  public String getMyTitle() {
    return myTitle;
  }
}

We can explore more things about sightly in next article !!!
 
Cheers!!!
SonyCharan

Sightly api, comparing, accessing arrays with sightly in AEM

Here we will discuss about:
       ·          How to use arrays with slightly
       ·         How to compare
       ·         How to use API - Some scenarios

Arrays :
Here a sample around arrays:
// accessing a value from properties
${ properties['jcr:title'] }

// printing an array
${ aemComponent.names }

Printing the array, separated by ;
${ aemComponent.names @ join=';' }

// dynamically accessing values
<ul data-sly-list="${aemComponent.names}">
      <li>${ properties[ item ]}</li>
</ul>

Comparisons:
Here some use-cases 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>

Now we will look at the API part and some scenarios here:

Use-API :
In my prvious article I explained that you can call methods from your custom-classes via the data-sly-use notation.
Now explaining, you can also pass in parameters from your components.
<div data-sly-use.aemComponent="${'com.myproject.components.SightlyComponent' @ firstName= 'feike', lastName = 'visser'}">
     ${aemComponent.fullname}
</div>

Java-code in the Use-Api
                    public class SightlyComponent extends WCMUse {
   // firstName and lastName are available via Bindings
  public String getFullname() {
    return get("firstName", String.class) + " " + get("lastName", String.class);
  }
}

The basic notation of the use-api looks like this is a Sightly component.

<div data-sly-use.mycomp="${ 'com.demo.MyComponent'
@ param1='value1', param2=currentPage}">
    ${mycomp.calculatedValue}
</div>

In this example you have the following:
  • the class ‘com.demo.MyComponent’ is instantiated
  • the name ‘mycomp’ is used
  • two parameters are passed to the class
  • the method getCalculatedValue() is called
  •  
Now let’s look at the implementation of this; you have 5(!) options to implement this:
  1. Class that implements the Use-interface
  2. Class that extends WCMUse-class
  3. Class that is adaptable from Resource (resource.adaptTo(YourClass))
  4. Class that is adaptable from SlingHttpServletRequest (request.adaptTo(YourClass))
  5. Sling models

Below I will do an example of each option, so you can see what is needed for each.
With all 5 scenarios you can switch the implementation without changing anything in your component.

Scenario-1: Class implementing Use-interface
In this case you need to implement init(), and do the all the logic in there. Via the bindings-object you can access all the objects also available on the component.
import io.sightly.java.api.Use;

public class MyComponent implements Use {
  private String value;
  @Override
  public void init(Bindings bindings) {
    // all standard objects/binding are available
    Resource resource = (Resource) bindings.get("resource");
    // parameters are passed as bindings
    String param1 = (String) bindings.get("param1");
    Page param2 = (Page) bindings.get("param2");
    value = param1 + resource.getPath() + param2.getTitle();
  }

  public String getCalculatedValue() {
    return value;
  }
}

Scenario-2: Class extending WCMUse
This option is similar like the Use-interface, but has some more helper functionality that you can use. Methods like getResource(), getCurrentPage() etc are already there for you to use.
import com.adobe.cq.sightly.WCMUse;

public class MyComponent extends WCMUse {
  private String value;

  @Override
  public void activate() {
    // helper method to get the default bindings
    Resource resource = getResource();
    // access to the parameters via get()
    String param1 = get("param1", String.class);
    Page param2 = get("param2", Page.class);
    value = param1 + resource.getPath() + param2.getTitle();
  }

  public String getCalculatedValue() {
    return value;
  }
}
Scenario-3: Class adaptable from Resource
Code example given here is how to adapt your class from a Resource. Based on that Resource-object you need to pass in the right info to your POJO. In this case you can have a plain POJO without any dependency to AEM or Sightly.
NOTE: In this option you can’t access the parameters
@Component(metatype = true, immediate = true)
@Service
public class MyComponentAdapter implements AdapterFactory {

  @Property(name = "adapters")
  protected static final String[] ADAPTER_CLASSES = { MyComponent.class.getName() };

  @Property(name = "adaptables")
  protected static final String[] ADAPTABLE_CLASSES = { Resource.class.getName() };

  @Override
  public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
    if (adaptable instanceof Resource) {
       MyComponent comp = new MyComponent();
       return (AdapterType) comp;
    }
    return null;
  }
}
Scenario-4: Class adaptable from Request
Like option 3, but now based on the request. Also it is possible here to access the parameters; they are passed in as attributes.
@Component(metatype = true, immediate = true)
@Service
public class MyComponentAdapter implements AdapterFactory {

  @Property(name = "adapters")
  protected static final String[] ADAPTER_CLASSES = { MyComponent.class.getName() };

  @Property(name = "adaptables")
  protected static final String[] ADAPTABLE_CLASSES = { SlingHttpServletRequest.class.getName() };

  @Override
  public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
    if (adaptable instanceof SlingHttpServletRequest) {
      SlingHttpServletRequest request = (SlingHttpServletRequest) adaptable;
      String param1 = (String) request.getAttribute("param1");
      Page param2 = (Page) request.getAttribute("param2");
      return (AdapterType) new MyComponent();
    }
    return null;
  }
}
Scenario-5: Sling Models
You can technically implement Options 3 and 4 with Apache Sling Models; this saves you from creating your own adapters. Here’s an example of what that would look like:
@Model(adaptables=Resource.class)
public class MyComponent {

  @Inject
  private String firstname;
  private String value;

  @PostConstruct
  public void activate() {
    value = "calculate " + firstname;
  }

  public String getCalculatedValue() {
    return value;
  }
}
Use these test case scenarios and explore slightly !!!


Cheers!!!

SonyCharan

How to use Sightly in AEM


Sightly Introduction:

Sightly can referred as an HTML templating language, introduced with the version AEM 6.0.

It takes the place of JSP (Java Server Pages) and ESP (ECMAScript Server Pages) as the preferred templating system for HTML. The name “Sightly” (meaning “pleasing to the eye”) highlights its focus on keeping your markup beautiful, and thus maintainable, once made dynamic.
As in all HTML server-side templating systems, a Sightly file defines the output sent to the browser by specifying the HTML itself, some basic presentation logic and variables to be evaluated at runtime.

Why we use Sightly,

·         Security by Default
·         Separation of Concerns
·         Sightly is HTML5

How to use Sightly:

Every Sightly file is an HTML5 document or fragment, augmented with a specific syntax that adds the dynamic functionality. Here's a first example:
<h1 data-sly-test="${properties.jcr:title}">
${properties.jcr:title}
</h1>
Two different kind of syntaxes have to be distinguished:
  • Sightly Block Statements
    To define structural block elements within Sightly file, Sightly employs HTML5 data attributes. This allows to attach behavior to existing HTML elements. All Sightly-specific attributes are prefixed with data-sly-.
  • Sightly Expressions
    Sightly expressions are delimited by characters ${ and }. At runtime, these expressions are evaluated and their value is injected into the outgoing HTML stream. They can occur within the HTML text or within HTML attribute values.

<p data-sly-use.logic="logic.js">
    <a href="${logic.link}">
        ${logic.text}
    </a>
</p>

<h1 data-sly-test="${currentPage.title}">
    <a href="${currentPage.path}.html">
        ${currentPage.title}
    </a>
</h1>

Explanation for better understanding:
  • Line 1: The data-sly-test statement checks if the page title exists and is not empty. If so, the <h1> element and its content is displayed, otherwise it is removed altogether.
  • Line 2: This expression renders the page path into the href attribute. Since Sightly knows the HTML syntax, href and src attributes are automatically protected against cross-site scripting (XSS) injections accordingly. For instance if the variable contained a javascript: URL, it would have been removed.
  • Line 3: This expression displays the page title as text. Many special characters are escaped to make it impossible to inject cross-site scripts.

The main goals /objectives of sightly are :
        – giving back the markup, and not mixing it with code
        – everything is secure, by default
        – smoothen the workflow between the designer and the developer

Scenario-1:
<div>currentPageTitle : ${currentPage.title}</div>

  • Well that looks like a JSP, but not quite. Two main differences:
  • Extension of the file is changed to .html
  • We have only markup in the file, no inclusion of a global.jsp, just markup. So in case a designer wants to look at the file he can just open it in his tools

Scenario-2:
<div data-sly-test="${wcmmode.edit}">Showing this only in edit mode to the author</div>
When the expression inside data-sly-test evaluates to false the whole tag while be hidden in the markup.

Scenario-3:
<div data-sly-test.author="${wcmmode.edit || wcmmode.design}">
Show this to the author
</div>
<div data-sly-test="${!author}">
Not in author mode anymore.
</div>
data-sly-test also supports the naming and reuse of tests, we have an expression ‘author’ that we want to reuse in other data-sly-test attributes.
These are very common use-cases and can now be done without writing any code are extension.

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

data-sly-text will replace the value of the HTML-element with the expression of the data-sly-text.
In the example above the page-title will be printed. But the mock value can still be in there to make it easier to view the file in HTML-editors.
 
Scenario-5:
                    <ul data-sly-list.child="${currentPage.listChildren}">
                               <li>${child.title}</li>
                    </ul>
Here you see an example of a loop, the list object is passed to the data-sly-list attribute. Based on the name (‘child’) you can reference each item in the loop.The output is here that see you a list of the subpages with all the page-titles.

Scenario-6:
<ul data-sly-list.child="${currentPage.listChildren}">
          <li class="${ childList.odd ? 'odd' : 'even'}">${child.title}</li>
</ul>

Observations are:
  1. inside a data-sly-list you have access to a list-variable that contain things like : index, count, odd, even, first, last, middle
  2. in the expression you see the use of the ternary operator

Scenario-7:
                    <div data-sly-resource="${ @path='par', resourceType='foundation/components/parsys'}"></div>
With data-sly-resource you can include components and resources. In the above sample you include of standard cq parsys in your template.

Scenario-8:
    <footer data-sly-resource="${ @ path='footer', resourceType='myproject/footer', wcmmode='disabled'}"></footer>
So you are in need to disable the wcmmode for a specific component? That can now be done via the wcmmode-option when including a component.

Scenario-9:
                    ${pageProperties.jcr:title || properties.title || "No title"}
Within an expression you can use the ‘or’ operator to define fallbacks in case properties are empty. You read the expression from left to right, in the example here “No title” is shown when jcr:title and properties.title are both empty.

Scenario-10:
<div data-sly-include="/libs/wcm/core/components/init/init.jsp"></div>
 
<div data-sly-include="mytestfile.html"></div>

Via data-sly-include you can include other files like the cq:include tag. From sightly you can still use and re-use JSP files if you want. Like shown here for the author-environment.

We will discuss more in detail in our next posts.

Cheers!!!
SonyCharan