In JSTL you can set variables in on component that are available to all other components after it in the same request. In AEM using sightly is there an equivalent way to pass data between components ?
(the use case we are looking at is where we want one component to know when it's included via another component, rather than dragged into a parsys).
Assuming that with "requestScope" you mean request attributes, which are variables that are scoped to the request.
Setting request attributes is easily possible with Sightly's Use-API. This allows for instance to cache objects that are expensive to retrieve and that are accessed by multiple components of the same request.
What Sightly intentionally makes complicated is to set request attributes right before including a component and to remove them again right after, like the following JSP example:
<% request.setAttribute("myAttribute", someContextualInfo); %>
<cq:include path="innerComponent"/>
<% request.removeAttribute("myAttribute") %>
The reason why we don't want to encourage doing this, is that it isn't a clean pattern: it basically consists in using global variables as a way to communicate between resources... Global variables aren't exactly a best practice, even if you remove them again afterwards.
Try to see if following patterns wouldn't fit better to your needs:
1. Add Selectors
You can pass a dot-separated list of Sling selectors to the components included:
<div data-sly-resource="${'innerComponent' @ addSelectors='foo.bar'}"></div>
The myComponent
component can then for instance contain a foo.html
, a bar.html
, and a foo/bar.html
template that would render the different combinations of selectors. But you can also act differently based on the selectors by programmatically accessing them through the RequestPathInfo.
The selectors method has the benefit that you can call your component's content node with various desired selector(s) to choose what rendition of the node you wish:
http://localhost:4502/content/my/content/node.foo.bar.html
One thing to be aware though about this approach, is that if you use selectors with a (theoretically) unbounded set of values, you will see subtle performance problems at first and then eventually blow out the script resolver cache. Selectors should only be used with a (relatively small) bounded set of values.
2. Walking Up
In case you only want to pass a context to some components depending on the parent component that includes it, then it is better to turn the problem upside down and on the child component to walk up the tree of parent nodes and act accordingly.
Imagine for instance that you'd like to add a CSS class to a listItem component based on the parent component that used it in order to add something like the list-item-<parent-component-name>
class to the rendition of the listItem:
<li class="list-item list-item-user">User Name</li>
In JSP it is tempting to solve it as follows:
<% request.setAttribute("parentClassName", "user"); %>
<cq:include path="list-item"/>
<% request.removeAttribute("parentClassName") %>
But this is actually not necessary as the child component could check what it's parent component is and figure out by itself what the appropriate value of the parentClassName
should be. The benefit is then that that child component could be called directly (for e.g. through AJAX to update the user list) and still render correctly.
3. Use-API
Now if the above two patterns don't correspond to what you need, then you might have not other way than to use request attributes. To do so, you can follow the method described on that other answer. But try to limit that practice as much as possible.