March 15, 2020
Estimated Post Reading Time ~

AEM JavaScript Use-API Part 2

ResourceUtils

ResourceUtils examples using an AEM Maven project and the We.Retail sample to show how to pass data from the HTL to server-side JavaScript, and use the /libs/wcm/foundation/components/utils/ResourceUtils.js to access properties from jcr:content.

For this first example, we’re using the AEM Maven Project Archetype 23 which already contains proxies to the core components, a content page template and a base page with some content.
To inspect the resource object, let’s extend the core container component and add an info.js file to it.
Using CRXDE, copy container.html from /apps/core/wcm/components/container/v1/container/ and paste into /apps/myproject/components/container/.
Create an info.js Use-API JavaScript in the /apps/myproject/components/container folder. e.g.,

info.js

"use strict";
use( function() {
  log.info('### ' + resource);
});
Edit the end of the /apps/myproject/components/container/container.html HTL template to use the info.js. e.g.,

container.html

    ...
   
    <sly data-sly-use.info="info.js" />    
</sly>
Load the base page in “View as Published” mode using the wcmmode=disabled querystring. e.g., http://localhost:4502/content/myproject/us/en.html?wcmmode=disabled
In the crx-quickstart/logs/error.log, read the log.info('### ' + resource) output from our info.js. Since the container is used on both the en page and respective content page template, there is a log entry being written for each instance. e.g.,

error.log

07.03.2020 11:40:56.130 *INFO* [127.0.0.1 [1583599256071] GET /content/myproject/us/en.html HTTP/1.1] apps.myproject.components.container.container$html ### /content/experience-fragments/myproject/us/en/site/header/master/jcr:content/root
07.03.2020 11:40:56.150 *INFO* [127.0.0.1 [1583599256071] GET /content/myproject/us/en.html HTTP/1.1] apps.myproject.components.container.container$html ### /content/myproject/us/en/jcr:content/root/container/container
07.03.2020 11:40:56.150 *INFO* [127.0.0.1 [1583599256071] GET /content/myproject/us/en.html HTTP/1.1] apps.myproject.components.container.container$html ### /conf/myproject/settings/wcm/templates/page-content/structure/jcr:content/root/container
07.03.2020 11:40:56.157 *INFO* [127.0.0.1 [1583599256071] GET /content/myproject/us/en.html HTTP/1.1] apps.myproject.components.container.container$html ### /content/experience-fragments/myproject/us/en/site/footer/master/jcr:content/root
07.03.2020 11:40:56.157 *INFO* [127.0.0.1 [1583599256071] GET /content/myproject/us/en.html HTTP/1.1] apps.myproject.components.container.container$html ### /conf/myproject/settings/wcm/templates/page-content/structure/jcr:content/root
For more info on logs, see the Debugging / Logging section from this series.
This shows us what are resource value is. Now let’s use this value with ResourceUtils.getResource. Replace the contents of container/info.js as follows.

info.js

"use strict";
use(["/libs/wcm/foundation/components/utils/ResourceUtils.js"], function (ResourceUtils) {
  var data = {};
  ResourceUtils.getResource(resource + "/helloworld")
  .then(function (node) {
    var props = node.properties;
    data.text = props["text"];
  });
  return data;
});
This will return the text property value from the HelloWorld component within the container component.
Update the end of our /apps/myproject/components/container/container.html template to output the data being returned. The data-sly-test attribute on the pre element is testing if the info.text value exists before it will render itself.

container.html

  ... 
    <sly data-sly-use.info="info.js">
        <pre data-sly-test="${info.text}">
          helloworld text property: ${info.text}
        </pre>
    </sly>
</sly>
Load the base page in edit mode to see the helloworld text property value being output in the parent container.
localhost:4502/content/myproject/us/en.html

We.Retail Example

For this example we’ll be using crx/de in author runmode to edit the weretail app directly on the server. e.g., http://localhost:4502/crx/de
In /apps/weretail/components/structure/page create a file named example.js as follows.
"use strict";
use(["/libs/wcm/foundation/components/utils/ResourceUtils.js"], function (ResourceUtils) {
  var data = {};
  data.key = this.key;
  ResourceUtils.getResource("/content/we-retail/us/en/" + this.key + "/jcr:content")
  .then(function (node) {
    var props = node.properties;
    data.title = props["jcr:title"];
  });
  return data;
});
In the server-side JavaScript file, access the value of parameters using this, for example this.key.

Passing Data

With HTL, we can pass data into the server-side JavaScript in the data-sly-use value as a parameter. For example.
Edit /apps/weretail/components/structure/page/body.html and add these two sly elements and a pre element before the closing div as follows.
<div class="container">
    ...
    <sly data-sly-test.key="${request.requestParameterMap['key'][0].toString}"/>
    <sly data-sly-use.example="${'example.js' @ key=key}"></sly>
    <pre>
    example.title: ${example.title}
    </pre>
</div>
The first sly element sets a variable named key using the value from the key query string parameter in the request.
The second sly element, sets a variable name example using data-sly-use.example. It declares the server-side example.js file as the source and passes a parameter named key into the JavaScript. The key contains the key value that was declared in the first sly element.
Using a query string parameter, we can access the jcr:content for the page node supplied as the key. To test this, load http://localhost:4502/content/we-retail/us/en.html?key=about-us in a new browser tab. This request has the query string key parameter set to about-us. In the example.js we’re using the key parameter value to lookup the content for the about-us node.
Scroll down the page and note the values output in the pre the element we added to test the results returned by the Use-API JavaScript.
If we inspect /libs/wcm/foundation/components/utils/ResourceUtils.js in CRXDE Lite, you can see all of the available methods and logging that is taking place.
For example, the getResource method.
/**
  * Resolves a resource
  *
  * @returns promise as returned by the granite.resource.resolve or undefined if
  *          the 'granite' cross-platform API is not available
  */
ResourceUtils.getResource = function (resourcePath) {
    var resolvedResource = undefined;
    if (typeof granite != "undefined") {
        // resolve based on cross platform API
        log.debug("Found 'granite' cross-platform namespace, using it to resolve " + resourcePath + " path");
        resolvedResource = granite.resource.resolve(resourcePath);
        log.debug("Resolved resource " + resourcePath);
    } else {
        log.error("Can't find 'granite' cross-platform namespace!");
    }
   
    return resolvedResource;
}
return ResourceUtils;

Functions

Here is an example of how to use functions in the server-side JavaScript. Suppose you would like to ensure that a property value is title cased when sent to the Sightly (HTL) file? Using a function, we can pass the property value into a function that returns it in title case. Here, we add a function named toTitleCase in the existing example.js file we created earlier. We will pass it the jcr:title property as a str parameter to be returned Title cased. e.g.,
"use strict";
use(["/libs/wcm/foundation/components/utils/ResourceUtils.js"], function (ResourceUtils) {
  var data = {};
  data.key = this.key;
  ResourceUtils.getResource("/content/we-retail/us/en/" + this.key + "/jcr:content")
  .then(function (node) {
    var props = node.properties;
    data.title = toTitleCase(props["jcr:title"]);
  });
  function toTitleCase(str) {
    var _str = new String(str);
    return _str.replace(/(^|\s)[a-z]/g, function(chr){ return chr.toUpperCase() });
  }
  return data;
});
To test the new function, using crx/de select the /content/we-retail/us/en/about-us/jcr:content resource and edit the jcr:title property value by updating with a lower case string. e.g., About Us test

Save the changes in /crx/de and load / reload http://localhost:4502/content/we-retail/us/en.html?key=about-us. Scroll down to see the jcr:title rendered in Title case, e.g., example.title: About Us Test.



By aem4beginner

No comments:

Post a Comment

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