How to check if child component resource exist or not using Sightly in AEM? - aem

my component has an embedded image component inside of it, i need to show image only if image component is authored,
Component Code:
<div class="col-md-4">
<sly data-sly-resource="${'image' # resourceType='test/components/content/image'}"></sly>
</div>
So i need to check resource of embedded image component authored or not
i know we can do this in Java, but how to do this in Sightly?

This can be doable ,using ${resource['image/jcr:primaryType']},
here image is child component
<sly data-sly-test="${resource['image/jcr:primaryType']}">
<div class="col-xs-5 col-md-4">
<sly data-sly-resource="${'image' # resourceType='test/components/content/image'}"></sly>
</div>
</sly>

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

Remove ce-wrappers of fluid cObject

I masked(mask-extension) a couple of plug-ins. When the image is generated in the template, it is always wrapped in following divs:
<div id="c63" class="frame frame-default frame-type-image frame-layout-0">
<div class="ce-image ce-center ce-above">
<div class="ce-gallery" data-ce-columns="1" data-ce-images="1">
<div class="ce-outer">
<div class="ce-inner">
<div class="ce-row">
<div class="ce-column">
<figure class="image"><img class="image-embed-item"
src="fileadmin/user_upload/bla" width="975"
height="678" alt=""></figure>
</div>
</div>
</div>
</div>
</div>
</div>
Is there any way to remove all those wrappers? I simply want to have the image.
Sidenotes:
1. f:image does not work, I cannot access the proper uid for it to show. (This is perhaps an issue with mask)
2. I cannot find the tt_content.stdWrap.innerWrap > in my typoScript, as I do not know where mask puts it. It is neither in the netup.ts nor in the NewContentElementWizard.ts
You need to overwrite the fluid_styled_content partial in Resources/Private/Partials/Media/Gallery.html.
How to overwrite, you can read here: https://docs.typo3.org/typo3cms/extensions/fluid_styled_content/8.7/Configuration/OverridingFluidTemplates/

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>

CQ5 Sightly Accordion component

Hi am trying to design an accordion component using sightly in AEM where instead of jsp we write html code along with different file for css and js under client libs.
I simply coded the below written part and wrote js for the same but am not able to see any changes ... Could someone please provide me a solution to implement the same.. ->when i click on show a parsys section opens up and when show converts to hide and when i click on hide the parsys section closes and hide converts to show.
<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap>
<css data-sly-call="${clientLib.css # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
<js data-sly-call="${clientLib.js # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
</div>
<div data-sly-test="${wcmmode.edit}">Accordion_2 component</div>
<div class="about-contentcontainer">
<div class="about-content">
<div class="awards">
<h4> <span class="more">Show</span></h4>
<h4> <span class="more expanded">Hide</span></h4>
</div>
</div>
</div>
<script>// <![CDATA[
$(document).ready(function() {
alert("Hello");
$(".awards h4 a").click(function() {
enter code here
$(this).parent().next().slideToggle("slow");
var htmlStr = $(this).find(".more").html();
if (htmlStr == "Show") {
$(this).find(".more").html("Hide");
$(this).find(".more").addClass("expanded");
} else {
$(this).find(".more").html("Show");
$(this).find(".more").removeClass("expanded");
}
});
});
// ]]></script>
Looking at it, I think that this has little to do with Sightly or even with AEM. Also, I'm not sure which content you want to toggle.
Below's a working HTML fragment for toggling content (independent from AEM):
<style>
.toggle-content {
display: block;
}
.toggle-content-hide,
.toggle-content-hidden .toggle-content-show {
display: inline;
}
.toggle-content-show,
.toggle-content-hidden .toggle-content-hide {
display: none;
}
</style>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 1</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 2</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
jQuery(function($) {
$('.toggle-content').click(function () {
$(this).toggleClass('toggle-content-hidden').next().toggle('slow');
return false;
})
});
</script>
To implement this in AEM, you should place the inline CSS into a CSS file of a client library, and the inline JS into a JS file of a client lib. I usually recommend to place them in the same client library within the component itself, so that everything that relates to that component is in the same folder. But when doing so, it is important to keep in mind that on a publish server, all /apps requests are forbidden by the dispatcher for security reasons, so all client libraries located under /apps should be merged and minified as one file that is typically located somewhere under /etc. To do so, you can use following repository node structure:
/apps/
mysite/
components/
mycomponent/
mycomponent.html Sightly template
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.mycomponent]
css.txt contains just a reference to style.css
style.css contains the style snippet
js.txt contains just a reference to script.css
script.js contains the script snippet
/etc/
designs/
mysite/
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.publish]
embed = [mysite.mycomponent, ...]
dependencies = [mysite.jquery]
The embed property of the /etc clientlib will make that it embeds and merges within the same file all clientlibs that are listed there. As opposed to the client libraries listed under the dependencies property, which will not get merged and will be served as a separate file. You can play with these properties to build the structure you need to optimize your site. There are also settings to automatically minify or not these files.
On the page, you then include the mysite.publish master clientlib located under /etc. So your page <head> element, would contain something like following Sightly template:
<head data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientLib.all # categories='sd-singtel.accordion_2'}" data-sly-unwrap/>
</head>
If you're using AEM 6.1, you can even drop the data-sly-unwrap, because the <sly> tag has the same effect.
After that, the Sightly template of your component located under a path like /apps/mysite/components/mycomponent/mycomponent.html would look as follows:
<div data-sly-test="${wcmmode.edit}">mycomponent name</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>${properties.myContentProperty}</div>