May 9, 2020
Estimated Post Reading Time ~

Sightly API, comparing, accessing Arrays with Sightly in AEM

Sightly api, comparing, accessing arrays with sightly in AEM
Here we will discuss:

  1. How to use arrays with slightly
  2. How to compare
  3. 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:
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:

  1. the class ‘com.demo.MyComponent’ is instantiated
  2. the name ‘mycomp’ is used
  3. two parameters are passed to the class
  4. the method getCalculatedValue() is called 

Now let’s look at the implementation of this; you have 5(!) options to implement this:

  1. The class that implements the Use-interface
  2. The 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 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 to the User-interface but has some more helper functions 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
The 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 on 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 !!!


By aem4beginner

No comments:

Post a Comment

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