Unable To Get Implicit Objects In WCMPojo - aem

I am using a component where there is need of dynamic dropdown. The options are configured in the page properties. But I am unable to get currentPage Object in datasource.html file. Below is the structure of my component.
And datasource calling the wcmpojo class. Below in the flow.
datasource.html
<sly data-sly-use.data="${'apps.myprj.components.content.tabcontent.HtlDatasourceExample' # text=currentPage.path}">
</sly>
HtlDatasourceExample is getting call and resulting correct response if values are hardcoded.
Issue is unable to get sling objects in HtlDatasourceExample such as currentPage.
Thanks

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.

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.

data-sly-resource error handling in sightly - AEM

data-sly-resource tag allows to refer resource in another component in following way.
<article data-sly-resource="path/to/resource"></article>
We have path/to/resource being taken as part of dialog field by content authors. If the content authors select the path which is not existing by mistake, page becomes inaccessible to content authors, giving HTTP 500 error and there is no other way to correct it without going to CRX. On environments where access to CRX is not there, we cannot delete the incorrect node. Exception in logs is
Caused by: org.apache.sling.scripting.sightly.SightlyException: org.apache.sling.api.resource.ResourceNotFoundException: No resource found
at com.adobe.cq.sightly.WCMScriptHelper.includeResource(WCMScriptHelper.java:143)
at com.adobe.cq.sightly.WCMScriptHelper.includeResource(WCMScriptHelper.java:86)
at com.adobe.cq.sightly.internal.extensions.ResourceExtension.call(ResourceExtension.java:99)
at org.apache.sling.scripting.sightly.impl.engine.runtime.RenderContextImpl.call(RenderContextImpl.java:89)
The out of the box reference component (/libs/foundation/components/reference/reference.jsp) handles this by having a catch block, Content Author can correct path. But that's JSP based not sightly based.
Is there a way to handle this in sightly?
The proper way to handle this is through an Use-API object that will attempt to find the resource and handle any exceptions:
<article data-sly-use.helper="myHelper" data-sly-test="${helper.resource}" data-sly-resource="${helper.resource}"></article>
Passing an actual org.apache.sling.api.resource.Resource to data-sly-resource is possible since SLING-5811, for older versions of HTL/Sightly you will need to pass a path.
Try this syntax, path should given in EL expression:
<article data-sly-resource="${ # path='path/to/resource'}"></article>

AEM DefaultValue written to JCR

I noticed that when I set my defaultValue for a dropdown, altho it is correctly selected in the drop down when I first add my component to the page it does not write the defaultValue to the corresponding JCR until I edit the component and save it. Even if I just open the corresponding dialog and click OK now my component works as expected because the values have been added to the JCR.
I am sure there is an important piece that I am missing here, does anyone knows how defaultValues that are required in order for the component to render properly can be added to the JCR when they are first added to the page?
Like Shwan say's that's the way it works. The default values or empty texts are only for the dialog. They aren't persisted until the dialog is authored. The properties have to be set by a different method. CQ already ships with this feature and you can do it without any custom code.
Under your component , create a node called cq:template[nt:unstructured] . If all the data is stored on the component node itself , add the default values as properties to cq:template node with name same as the ones in your dialog. In case the data is stored in a child node add a similar node under cq:template node.
Source : http://blogs.adobe.com/experiencedelivers/experience-management/defaults-in-your-component/
I believe that is simply the way it works. The default value specified in a dialog does not get used until the dialog is loaded/saved, so until that happens the node on the JCR repository that is being authored won't have the default value.
We got around this on a project by adding back-end code that was tied to the component (a tag) so that when the component was loaded, if the property did not exist, it would be written with the default the first time. Ex:
if (wcmMode == WCMMode.EDIT )
{
if(!currentNode.hasProperty("SomePropertyThatWillAlwaysExistIfTheDialogHasBeenSaved")) {
currentNode.setProperty("PropertyThatShouldHaveDefault", GlobalConstants.TRUE);
currentNode.getSession().save();
}
}
Like Sharath Madappa say's that's the way it works fine if component name and jsp name same. If you dont have componentname.jsp under component or page, cq:template won't work.(Reference:http://labs.6dglobal.com/blog/2014-07-08/using-the-cq-template/)
If you hava componentname.html under your component, changed the node [cq:template] type to [cq:Template] instead of [nt:unstructured]. In this case, defaultValues can be added to the JCR when they are first added to the page.

Preselected value in the PrimeFaces autoComplete

Is there a way to "combine" the SelectOneManu and autoComplete feature?
When the form is loaded I'd like that input field to display the current value of the bean property, plus ability to select a new value with autoComplete.
Primefaces already provides this already in the autocomplete component. Just look on the demo site. By adding the dropdown="true" on the autocomplete menu, you enable support for a dropdown. Concretely, follow the following steps to get your results
Set dropdown="true" on your autocomplete menu. Then set the completeMethod to correspond to a method on your backing bean that returns a list of the items you want to show up in the dropdown menu.
To preset the value on the autocomplete component, simply initialise the value in the backing bean to whatever you want. Take the following as an example. If you have
<p:autoComplete id="dd" dropdown="true" value="#{yourBackingBean.myVariable}" completeMethod="#{yourBackingBean.loadOptions}" />
In your backing bean, you initialise the myVariable type during it's declaration
String myVariable = "Desired Value";
If you're going to be populating the dropdown list with a list of complex/POJO types (and as a result, bind the value attribute to a complex type in the backing bean), you'll need to use the converter based autocomplete component implementation