AEM 6.0: Pass dynamic value to clientlibs #categories - aem

I am trying to pass dynamic value while calling clientlibs to # categories using HTL but it is not picking the value.
Snippet of code:
<sly data-sly-use.config="com.demo.core.sightly.page.Config">
<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}">
<js data-sly-call="${clientLib.js # categories='${config.clientLibFolder}'}"></js>
</sly>
</sly>
While I am printing the value ${config.clientLibFolder} it is coming.
Is there any way I can pass dynamic value to #categories while calling clientlibs.

The syntax appears to be wrong. Did you try
<js data-sly-call="${clientLib.js # categories=config.clientLibFolder}"></js>
Or
<js data-sly-call="${clientLib.js # categories=[config.clientLibFolder]}"></js>

Related

AEM different ways to use HTL sly

What is the difference between to use:
<div data-sly-resource="${'foo' # resourceType="var"} ... ></div>
or
<sly data-sly-resource="${'foo' # resourceType="var"} ... ></sly>
or
<sly data-sly-resource="${'foo' # resourceType="var"} ... />
And when I should use data-sly-unwrap?
I think the best way to understand when to use what, is to understand the fundamentals of HTL.
Most of HTL can be written around existing HTML tags and attributes, such as
<div data-sly-resource="${'foo' # resourceType='var'}" ... ></div>
However, in instances where you don't want the HTML element to be present in the output, you can leverage the sly element. When an sly element is used it is removed from the final rendered HTML automatically.
For e.g.,
<sly data-sly-resource="${'foo' # resourceType='var'}" ... ></sly>
or
<sly data-sly-resource="${'foo' # resourceType='var'}" ... /> both output the same HTML which is directly including the output of the resource foo without adding any extra tags.
But if the same was written using an HTML element such as the following
<div data-sly-resource="${'foo' # resourceType=""var}" ... ></div>
the generated HTML will contain a parent div tag around the included resource's output as shown below
<div>HTML output of foo goes here</div>
The data-sly-unwrap comes into play in such scenarios. Adding the data-sly-unwrap to an HTML element will exclude that element from the generated output, but would output all the child HTML.
For e.g., <div data-sly-resource="${'foo' # resourceType='var'}" ... data-sly-unwrap></div> and <sly data-sly-resource="${'foo' # resourceType='var'}"></sly> and <sly data-sly-resource="${'foo' # resourceType='var'}" /> would produce the same output.
Please note that the data-sly-unwrap on a sly element has no effect as the sly is removed by the processor anyways.
However, I think the power of data-sly-unwrap lies when using it with conditional statements.
For e.g., if a parent element needs to present only in certain scenarios, then using it in the following way is much cleaner than writing multiple if conditions as we used to do in JSPs or JSTLs.
<div class="parent" data-sly-unwrap="${hideParent}">
<img class="img" src="../../xyz.jpg" />
</div>
More on data-sly-unwrap here.

AEM - data-sly-resource children html

I want to figure out a way to insert HTML inside a <sly data-sly-resource> tag and be able to go inside the component I am retrieving from the resource attribute.
To compare, it would be something like Vue's slots, and React's { this.props.children }.
Example:
Parent Component
<sly data-sly-resource="${'example' # resourceType='path/to/component/structure/example'}">
<h1>Hello World</h1>
</sly>
Example Component
<div id="example-component">
${ variable.getChildrenHTMLCall() } // Does something like this exist?
</div>
Output
<div id="example-component">
<h1>Hello World</h1>
</div>
This functionality does not exist.
You could make a similar functionality by using data-sly-template. But you’d have to pass the HTML sting as a parameter (more specifically option) but that might not be desired or maintainable.
You could use the com.day.cq.contentsync.handler.util.RequestResponseFactory as seen here: http://www.nateyolles.com/blog/2015/10/get-rendered-html-for-an-aem-resource-or-component

AEM Sightly - passing a variable to JS

I'd like to pass a value into my JS via Sightly.
Something like this:
<div data-sly-use.test="'test.js' # value='${v}'">
But the syntax is wrong?
This is obviously wrong too:
<div data-sly-use.test="'${test.js' # value='${v}'}">
Any ideas?
As explained on this sightly page, you need to pass value inside ${}.
https://docs.adobe.com/docs/en/aem/6-1/develop/sightly/use-api-in-javascript.html
Try this:
<div data-sly-use.test="${'test.js' # value=v}">

How to set variable from use object in sightly?

I have plain use class which contains one method that returns complex bean with a lot of setters/getters. Lets name it SomeUse. Given sightly file:
<sly data-sly-use.someUse="com.mycompany.SomeUse">
${someUse.data.firstProperty}
<div>
${someUse.data.secondProperty}
</div>
<!-- ...and so on -->
</sly>
So the point is I don't want to look at someUse.data getting. Instead of it I would do something like this:
<sly data-sly-use.someUse="com.mycompany.SomeUse" data-sly-use.data=${someUse.data}>
${data.firstProperty}
<div>
${data.secondProperty}
</div>
<!-- ...and so on -->
</sly>
I can't do this way though. Is there any alternative to achieve such result? Thanks a lot!
So the answer is to:
<sly data-sly-test.varName="${data.firstProperty}"></sly>
<div> ${varName.secondProperty} </div>
Creating a variable through empty data-sly-test attribute make it accessible after a tag.
You can set variables for use in a WCMUse class with the following syntax:
<sly data-sly-use.someUse="${ 'com.mycompany.SomeUse' # page=currentPage }">
and retrieve the page variable from your WCMUse class's activate() method like this:
Page page = get("page", Page.class);
For a working example, check out this Sightly script and this WCMUse class.
Instead of data-sly-use.data=${someUse.data}
use data-sly-test.data="${someUse.data}".
Then you will be able to get the property like
${data.firstProperty}
<div>
${data.secondProperty}
</div>
You can also set in DOM elements
<div id="elementId" data-sly-test.vehicle="${model.vehicle}">
<p>${vehicle.name}</p>
<p>${vehicle.type}</p>
</div>

Evaluating expression and pass as argument in Sightly AEM

I have the following Sightly expression:
<li data-sly-call="${linkTemplate.dynamicLink # section='education',
url='/en/life-career-events.html', text=${'comp.masthead.navigation.home' # i18n}}">
</li>
The dynamiclink template is as follows:
<div data-sly-template.dynamicLink="${# section, url, text}"
data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation' # section=section}">
<a data-sly-attribute.class="${membersNav.cssClass}" href="${url}">${text}</a>
</div>
This doesn't work because text=${'comp.masthead.navigation.home' # i18n} isn't evaluated as a string and then passed into the dynamiclink.
Is this possible? Can I evaluate and assign to a variable or do I have to create a new template when I want to evaluate i18n lookups?
Sightly 1.1 doesn't allow to have expressions within expressions, and there's no plan to change that for now.
Hacking the solution:
There's a trick: data-sly-test can be (ab)used to set variables. It's not really a recommended way to do though, unless you have a real condition, because this will mislead someone who reads the template in thinking that the intention was to have an actual condition.
The trick goes like that: an identifier can be provided to data-sly-test, which will expose the result of the test as a variable. Additionally, data-sly-test will be considered true, unless the resulting string is empty.
For e.g.:
<p data-sly-test.spanishAsset="${'Asset' # i18n, locale='es'}">${spanishAsset}</p>
Outputs:
<p>Recurso</p>
So in your case, you could write:
<li data-sly-test.linkText="${'comp.masthead.navigation.home' # i18n}"
data-sly-call="${linkTemplate.dynamicLink # section='education',
url='/en/life-career-events.html', text=linkText}">
</li>
A cleaner solution
As you probably don't want to explain to all the users of this template that they have to write such a hack, and instead of having two separated templates for translated and non-translated texts, you could instead leverage optional templates parameters. So you might for e.g. have a noI18n optional parameter.
The call would then be as simple as it can be:
<!--/* Translating would be the default behavior */-->
<li data-sly-call="${linkTemplate.dynamicLink #
section='education',
url='/en/life-career-events.html',
text='comp.masthead.navigation.home'}"></li>
<!--/* Or translating could be turned off */-->
<li data-sly-call="${linkTemplate.dynamicLink #
section='education',
url='/en/life-career-events.html',
text='my text...',
noI18n=true}"></li>
The template would then have two data-sly-test conditions for the two cases (note that the data-sly-unwrap attributes can be dropped in AEM 6.1+):
<div data-sly-template.dynamicLink="${# section, url, text, noI18n}"
data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation'
# section=section}">
<a href="${url}" data-sly-attribute.class="${membersNav.cssClass}">
<sly data-sly-test="${noI18n}" data-sly-unwrap>${membersNav.text}</sly>
<sly data-sly-test="${!noI18n}" data-sly-unwrap>${membersNav.text # i18n}</sly>
</a>
</div>
Optionally, to keep the template as simple as possible and to remove those conditions, you could also make the Use-API do the translation, depending on the noI18n optional parameter:
<div data-sly-template.dynamicLink="${# section, url, text, noI18n}"
data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation'
# section=section, noI18n=noI18n}">
<a href="${url}" data-sly-attribute.class="${membersNav.cssClass}">
${membersNav.text}
</a>
</div>
The proper code for the logic to translate a string is:
Locale pageLang = currentPage.getLanguage(false);
I18n i18n = new I18n(slingRequest.getResourceBundle(pageLang));
String text = i18n.get("Enter a search keyword");