AEM 6.0: Additional parameters when using data-sly-resource?
Asked Answered
P

4

13

I am trying to implement something which I hope is relatively straight forward... I have one component (lets call it the wrapper component) which contains another component (lets call it the inner component) inside it via the data-sly-resource tag:

<div data-sly-resource="${ 'inner' @ resourceType='/projectname/components/inner' }"></div>

I would like to pass in some additional parameters with this tag, specifically a parameter that can be picked up by sightly in the inner component template? I am trying to specify whether the inner templates outer html tag is unwrapped based on a parameter being passed in when the component is called via data-sly-resource.

After experimenting and perusing the sightly documentation, I can't find a way of achieving this.

Does anyone know if this is possible?

Many thanks,

Dave

Palatal answered 20/8, 2014 at 12:34 Comment(1)
possible duplicate of Are there requestScope variables in Sightly?Herakleion
H
9

You can use the Use-API to write and read request attributes if the alternatives proposed here don't work for you.

A quick example of two components where the outer component sets attributes that are then displayed by the inner component:

/apps/siteName/components/
    outer/ [cq:Component]
        outer.html
    inner/ [cq:Component]
        inner.html
    utils/ [nt:folder]
        setAttributes.js
        getAttributes.js
/content/outer/ [sling:resourceType=siteName/components/outer]
    inner [sling:resourceType=siteName/components/inner]

/apps/siteName/components/outer/outer.html:

<h1>Outer</h1>
<div data-sly-use="${'../utils/setAttributes.js' @ foo = 1, bar = 2}"
     data-sly-resource="inner"></div>

/apps/siteName/components/inner/inner.html:

<h1>Inner</h1>
<dl data-sly-use.attrs="${'../utils/getAttributes.js' @ names = ['foo', 'bar']}"
    data-sly-list="${attrs}">
    <dt>${item}</dt> <dd>${attrs[item]}</dd>
</dl>

/apps/siteName/components/utils/setAttributes.js:

use(function () {
    var i;
    for (i in this) {
        request.setAttribute(i, this[i]);
    }
});

/apps/siteName/components/utils/getAttributes.js:

use(function () {
    var o = {}, i, l, name;
    for (i = 0, l = this.names.length; i < l; i += 1) {
        name = this.names[i];
        o[name] = request.getAttribute(name);
    }
    return o;
});

Resulting output when accessing /content/outer.html:

<h1>Outer</h1>
<div>
    <h1>Inner</h1>
    <dl>
        <dt>bar</dt> <dd>2</dd>
        <dt>foo</dt> <dd>1</dd>
    </dl>
</div>

As commented by @AlasdairMcLeay, this proposed solution has an issue in case the inner component is included multiple times on the request: the subsequent instances of the component would still see the attributes set initially.

This could be solved by removing the attributes at the moment when they are accessed (in getAttributes.js). But this would then again be a problem in case the inner component is split into multiple Sightly (or JSP) files that all need access to these attributes, because the first file that accesses the request attributes would also remove them.

This could be further worked-around with a flag telling wether the attributes should be removed or not when accessing them... But it also shows why using request attributes is not a good pattern, as it basically consists in using global variables as a way to communicate among components. So consider this as a work-around if the other two solutions proposed here are not an option.

Herakleion answered 27/1, 2015 at 18:12 Comment(2)
One issue with this approach: if you want to pass an optional attribute, and had the same component appearing elsewhere on the page without setting these attributes. From what I can see, the subsequent instance of the component would load in the attributes from the previous data-sly-resource.Humpage
just realised we can probably get round this by clearing the variable in getAttributes.js (or similar) after it has been retrieved the first timeHumpage
E
5

There is a newer feature that request-attributes can be set on data-sly-include and data-sly-resource :

<sly data-sly-include="${ 'something.html' @ requestAttributes=amapofattributes}" />

Unfortunately it doesn't seem to be possible to construct a Map with HTL (=Sightly) expressions, and I don't see a way to read a request attribute from HTL, so you still need some Java/Js code for that.

Evangelistic answered 25/9, 2017 at 13:40 Comment(0)
D
0

unfortunately, no. there is no way to extend sightly functionality. you cannot add new data-sly attributes or modify existing ones. The best you can do is write your own helper using the USE API

Dowel answered 2/9, 2014 at 13:22 Comment(0)
D
0

If you just need to wrap or unwrap the html from your inner component in different situations, then you can just keep the html in the component unwrapped, and wrap it only when needed by using the syntax:

<div data-sly-resource="${ 'inner' @ resourceType='/projectname/components/inner', decorationTagName='div', cssClassName='someClassName'}"></div>

If you need more complex logic, and you need to pass a value to your inner component template, you can use the selectors. The syntax for including the resource with selectors is:

<div data-sly-resource="${ 'inner' @ resourceType='/projectname/components/inner', selectors='mySelectorName'}"></div>

The syntax to check the selectors in the inner component is:

${'mySelectorName' in request.requestPathInfo.selectorString}"

or

${'mySelectorName' == request.requestPathInfo.selectorString}"
Dioptometer answered 15/4, 2020 at 18:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.