Significance of # in AEM slightly - aem-6

Why we use # symbol in AEM slightly code. What is the significance of #?
For example:
<section data-sly-resource="${'./path' # resourceType='my/resource/type'}"></section>
In above code why # resourceType is used?

# is used in HTL/Sightly to pass parameters to the HTL block statements https://experienceleague.adobe.com/docs/experience-manager-htl/using/htl/block-statements.html?lang=en#request-attributes
If you check the above link you can see that the property settings.settings is passed as requestAttributes to the productdetails.html HTL file. It is same like passing arguments in a function, except that the syntax to do it in HTL/sightly is to use # with the parameter name and value
<sly data-sly-use.settings="com.adobe.examples.htl.core.hashmap.Settings"
data-sly-include="${ 'productdetails.html' # requestAttributes=settings.settings}" />

Related

AEM6.5 Passing paramater to the resource from HTL/Sightly template

I have a component that uses two different resources in its HTL/Sightly template.
Is there a way to pass a parameter, to the say in my example the eventResource template, so that I can depending on this passed paramter change a css class on it?
<ul data-sly-list.teasers="${model.resourceList}" class="teaser-list-alternating c-list--reset">
<sly data-sly-test="${teasers.eventTeaser}"
data-sly-resource="${teasers.resource # resourceType='xxx/components/content/eventTeaser'}"></sly>
<li data-sly-test="${teasers.contentTeaser}" class="l-stack l-stack--horse"
data-component-hook-content-hub="teaser"
data-sly-resource="${teasers.resource # resourceType='xxx/components/content/contentHubTeaser'}"></li>
</ul>
I tried using data-sly-resource="${teasers.resource # resourceType='xxx/components/content/eventTeaser', requestAttributes=model.config, selectors='blabla'} to no availability.
#RequestAttribute(name = "contentHub")
private String contentHub;
The requestAttribute contentHub in the eventTeaser model is alway null and I am not sure how to get the selectors value in the eventTeaser template.
I can do it using TypeScript on the front end part but it is not very clean.
I was able to solve it using the selectors indeed and reading the selector value directly from the other sightly template. Here is the documentation I refered to:
data-sly-resource="${teasers.resource # resourceType='xxx/components/content/eventTeaser', requestAttributes=model.config, selectors='inContentHub'}
 In the eventTeaser template I then used the following:
data-sly-set.inContentHub="${'inContentHub' == request.requestPathInfo.selectorString}
and depending on the value of the inContentHub variable I was able to change the css class which was my ultimate goal.

How to query XAML file with Powershell's `select-xml` commandlet?

I'm trying to use the select-xml cmdlet in Powershell to query some XAML files in my .NET project. Here's what I've tried:
select-xml -content (cat $xaml_file_path) -xpath "//GroupBox"
Where $xaml_file_path is simply a string containing the file path to the XAML file of interest.
This throws an error:
Select-Xml: Cannot validate argument on parameter 'Content'. The argument is null, empty, or an element of the argument collection contains a null value. Supply a collection that does not contain any null values and then try the command again.
I know the XAML is valid since it compiles fine on Visual Studio. So I'm thinking there might be something else going on here.
Is there a way to query XAML files using Powershell? If so how?
To query an XML (XAML) document that uses namespaces, Select-Xml requires you to:[1]
declare all the namespaces that any nodes involved in your XPath query are in, via a hashtable that maps self-chosen prefixes to namespace URIs (parameter -Namespace).
Those self-chosen prefixes may, but needn't, be the same as in the input document, with the exception of the default namespace (xmlns), for which a name must be chosen too, but which can not be xmlns (the example below uses _).
use those self-chosen prefixes for all the nodes referenced in the XPath query (parameter -XPath), including those in the default (implied) namespace.
A simple example:
# Create a sample XAML file.
#"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
Title="MainWindow" Height="450" Width="500">
<Grid>
<TextBox x:Name="UserInnput" Height="140" TextWrapping="Wrap" VerticalAlignment="Top" AcceptsReturn="True" AcceptsTab="True" Padding="4" VerticalScrollBarVisibility="Auto" />
<Button x:Name="Save" Content="Save" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" IsDefault="True" Height="22" Margin="170,150,0,0" />
</Grid>
</Window>
"# | Set-Content sample.xml
# Create the hashtable that uses self-chosen names to the URIs
# of those namespaces involved in the XPath query below.
$namespaces = #{
# This is the default namespace, which the elements in the input
# document that have *no* namespace prefix are *implicitly* in.
# You must NOT use 'xmlns' as the prefix.
_ = 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'
# For non-default namespaces, you may choose the same prefixes
# as in the original document.
# Note:
# * This namespace isn't actually used in the query below.
# * However, if the nodes involved in the query do fall into
# this or other namespaces, they must be declared here too,
# and their prefixes must then be used in the query.
x = 'http://schemas.microsoft.com/winfx/2006/xaml'
}
# Query the XAML file, passing the hashtable to -Namespace, and
# using its keys as namespace prefixes; here, '_:' must be used
# to refer to nodes in the default namespace.
Select-Xml -LiteralPath sample.xml -Namespace $namespaces -XPath '//_:TextBox'
If you want to avoid having to deal with namespaces:
In the context of Select-Xml (as well as the underlying System.Xml.XmlDocument.SelectNodes() .NET method), the only way to avoid having to deal with namespaces is to use the *[local-name()='...'] workaround shown in your own answer.
In the context of PowerShell's adaption of the [xml] DOM, which adds "virtual" properties to instances of [xml] (System.Xml.XmlDocument):
These properties are always named for the non-prefixed node names; that is, namespaces are effectively ignored.
This is convenient and often sufficient, but it limits you to "drilling down" with dot notation into the document, as opposed to having being able to run XPath queries against the document; for the latter, you can use the .SelectNodes() and .SelectSingleNode() methods, which, however, again necessitate namespace management.[1]
The equivalent example with dot notation, building on the same sample file:
# Parse the XML file into an [xml] instance.
($doc = [xml]::new()).Load((Convert-Path sample.xml))
# Drill down to the <TextBox> element.
# Note: If the <Grid> element had *multiple* <TextBox> children,
# they would *all* be returned, as a System.Xml.XmlElement array.
$doc.Window.Grid.TextBox
[1] The need for namespace management applies analogously to direct use of the underlying System.Xml.XmlDocument.SelectNodes() and System.Xml.XmlDocument.SelectSingleNodes() .NET API, although constructing the prefix-to-URI mapping table is a little more cumbersome there - see this answer.
I think that, similarly to xmllint there might be an issue with handling namespaces.
I've found that the following does work:
(select-xml -path $xaml_file_path -xpath "//*[local-name()='GroupBox']").Node
If anyone knows of a cleaner/better way to do this (i.e. using the -namespace flag), I would be curious to hear about it.

AEM 6.x: How to pass an HTL variable to clientlib/JS?

So I have the following lines which loads my javascript.
<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap />
<sly data-sly-call="${clientLib.js # categories='myhost.mycustomJS'}" data-sly-unwrap />
I have an HTL property (example: ${properties.myCustomProperty}) that I want to pass to myCustomJS.
Any ideas how it can be done?
I've looked around the net but didn't find anything useful.
Thank you.
You are trying to access a server side property with client side script. As you may realize sightly executes at server end and rendered output is returned to browser. In your case you need to send the properties to browser to make it available for clientside scripts to consume.
Technique 1: (Recommended) Data attributes -
This is easiest to send since DOM structure doesnt change. Pass the values as data elements and retrieve using jquery. For example:
var value = $('#mydiv').data('custom-property');
console.log(value);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv" data-custom-property="${properties.myCustomProperty}" />
Technique 2: (Old school) - Hidden variable - Add hidden variable into component rendering script; set the value of variable with HTL property and read the variable from clientside js using getElementById or jquery.
Technique 3: (Not recommended) - Make a trip to server. If you dont want to dilute your DOM (maybe property is secret or not SEO friendly), you may need to make an ajax call to a sling servlet that returns the property value. There are multiple examples available for sling servlet you can refer to.
ACS Sample, AEM 6.3 servlet, 1 more example.
But do remember its not worth to make a trip to server just for 1 property.

Pause interpolation of template string in FTL

I want to pass a dynamic string to FTL Macro. But I don't want the template string to be interpolated when I am calling the macro from FTL. I want the template string to be interpolated inside Macro only. So that I can make the Macro reusable by sending dynamic Template strings as parameter. As I am new to Apache FTL so I don't have much idea how to proceed.
Not sure what do you want to achieve, but I guess something like this:
<#macro m s>
<#local parsedS = s?interpret>
<#list ['John Doe', 'Jane Doe'] as name>
<p><#parsedS />
</#list>
</#macro>
<#m r"Hello ${name}!" />
which will print:
<p>Hello John Doe!
<p>Hello Jane Doe!
Some notes:
I haven't just used the parameter as a string with an interpolation,
but as an template fragment (so that auto-escaping, if you use it,
will be applied, also you could use #if and such in the value of
s).
As the template fragment is evaluated for multiple types in my
example, I have assigned the result of ?interpret to a local
variable, otherwise you could just write <#s?interpret />.
As of
the r before the string literal, that tells FreeMarker that ${}
(and \ escapes) must not be interpreted.

How can I pass a play template scala variable as input to a scala function?

Im not sure if i got the nomenclature right in the title of my question, Im new to play. Basically I wanted to break my html template by calling 2 sub-templates ( passing to them as argument an sub-object from the main template).
So my main template would be
#* patientInfoFrame Template File *#
#(alarm: Alarm)
#import helper._
#* Caller part *#
#calleInfoTemplate(#alarm.callee)
#* Patient part *#
#patientInfoTemplate(#alarm.patient)
where I receive an Alarm object as variable and would build part of the page by calling a second template calleInfoTemplate with a sub-object from the Alarm object and then a third template patientInfoTemplatewith another sub-object.
If I try to compile that it fails saying that #alarm.callee is an illegal start of simple expression.
How can I pass those sub-objects as input to the other templates?
You don't need the # escape character on your variables in this case because you are already inside a dynamic statement (the template call).
#* Caller part *#
#calleInfoTemplate(alarm.callee)
#* Patient part *#
#patientInfoTemplate(alarm.patient)