Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Storing output (<div>) of component into String instead of rendering it

Avatar

Level 4

Hi all,

 
Use case is:
We have global header and footer <div>s which we want to expose in form of JSON so that non AEM sites can read this JSON and render header and footer.I will store the content for header / footer using CQ component.
 
So for doing this I am thinking of somehow getting the output (<div>s) of a component into a string instead of rendering the output on page. Once we have this string we will expose same in form of JSON. What is the best way to implement this.
 
I am thinking of using a selector ( ".json") and then write a java/jsp code to output JSON.
http://localhost:4502:/content/global/header_footer.html.json
 
Below is the sample JSON which I am thinking of:
 
headerFooterJSON
{
   headerDiv : "<div> header markup here </div>",
   footerDiv : "<div> footer markup here </div>"
};
 
 
Thanks in advance.
 
Regards,
R
1 Accepted Solution

Avatar

Correct answer by
Level 4

Hi Jorg,

Some solution i found and thought sharing with you all. Let me know if you see any drawback of this approach.

Got a little solution for this after some digging. Sharing for everyone's benefit. Please let me know if you see any drawbacks of this solution.

 

There is a new attribute called "var" introduced in sling 1.3 taglibs. This attribute stores the final output of a component.

Apache Sling - Sling Scripting JSP Taglib

 

CQ 5.6.1 has sling tablib 1.0 so you will need to upload version sling taglib jar 1.3. You can download same from below link

http://repo1.maven.org/maven2/org/apache/sling/org.apache.sling.scripting.jsp.taglib/2.2.0/org.apache.sling.scripting.js…

 

You can just upload via felix console. Below is forum discussion around same

jsp - Using Sling Taglib version 1.3 in a CQ5.6.1 project - Stack Overflow

 

Now in yor JSP you will have to include this new taglib

<%@taglib prefix="sling1" uri="http://sling.apache.org/taglibs/sling"%>

 

and then do the <sling:include> with "var" attribute

<sling1:include path="/etc/designs/mysite/jcr:content/header.html" var="brandNavDiv"/>

 

and then you can read the "var" using pageContext

(String)pageContext.getAttribute("brandNavDiv"));

 

Remember CQ5.6.1 uses sling taglib version 1.0 so if you include /lib/foundation/global.jsp (which has version 1.0 then it will conflict ) then it will conflict.

 

 

Below is complete JSP code

---------------------------------------------------------------------------------

<%@ page import="org.apache.sling.commons.json.io.*,com.adobe.cq.*" %>

<%@ page import="org.apache.sling.engine.*" %>

<%@taglib prefix="sling1" uri="http://sling.apache.org/taglibs/sling"%>

<sling1:defineObjects />

 

<%

  response.setContentType("application/json");

%>

 

<sling1:include path="/etc/designs/mysite/jcr:content/header.html" var="headerDiv"/>

 

<%

response.setContentType("application/json");

JSONWriter writer = new JSONWriter(response.getWriter());

writer.object();

writer.key("header");

writer.value((String)pageContext.getAttribute("headerDiv"));

writer.endObject();

%>

=====================================================

 

copy paste from documentation page

=======================================================================================

sling:include

Includes a resource rendering into the current page.

  • Attributes
    • flush - Whether to flush the output before including the target.
    • resource - The resource object to include in the current request processing. Either resource or path must be specified. If both are specified, the resource takes precedences.
    • path - The path to the resource object to include in the current request processing. If this path is relative it is appended to the path of the current resource whose script is including the given resource. Either resource or path must be specified. If both are specified, the resource takes precedences.
    • resourceType - The resource type of a resource to include. If the resource to be included is specified with the path attribute, which cannot be resolved to a resource, the tag may create a synthetic resource object out of the path and this resource type. If the resource type is set the path must be the exact path to a resource object. That is, adding parameters, selectors and extensions to the path is not supported if the resource type is set.
    • replaceSelectors - When dispatching, replace selectors by the value provided by this option.
    • addSelectors - When dispatching, add the value provided by this option to the selectors.
    • replaceSuffix - When dispatching, replace the suffix by the value provided by this option.
    • scope - If var is specified, what scope to store the variable in. (Since 1.3)
    • var - ariable name to store the resulting markup into (Since 1.3)
  • Since: 1.0

=====================================================================================================

View solution in original post

6 Replies

Avatar

Level 4

Hi Jorg,

Happy New Year and thanks for your quick reply on this. Yes I was also thinking about this suggestion but this will create multiple calls from clients for getting header / footer (so in this case it will be 2 calls - one for header.html & 2nd for footer.html). We are trying to minimize the number of calls. So if its JASON call then it will be just 1 call instead of 2.

So how do we get the <div>s of a component into string so that i can construct my JSON

 

headerFooterJSON
{
   headerDiv : "<div> header markup here </div>",
   footerDiv : "<div> footer markup here </div>"
};

Avatar

Employee Advisor

(for the records: I somehow managed to delete my first posting. I proposed to fetch header and footer directly in dedicated requests as HTML from the component.)

Hi,

If you do these requests server-side, you can cache them, so it doesn't matter, if it's one or two requests. I would always prefer this approach, because it does not require changes to your AEM application code, even if you want to include other parts as well.

If you really want to include all fragments into a single JSON request, I would recommend to read [1] for a method to render a page (or parts of it) and get the HTML back.

kind regards,
Jörg

 

[1] https://cqdump.wordpress.com/2012/08/01/cq5-requesting-itself/

Avatar

Level 4

Hi Jorg,

Thanks for reply back.

Yes you are right that it won't  make much of difference if we make 2 separate calls. But I was reading these blogs and here its mentioned that its good to reduce number of call for various reason like reducing HTTP traffic , broswer restriction on how many call they can handle , get advantage of compression 

http://stackoverflow.com/questions/3138371/very-large-http-request-vs-many-small-requests

http://stackoverflow.com/questions/12200973/better-many-small-ajax-request-or-a-big-one-for-global-s...

Let me go through the link which you have shared. Will let you know if I have further questions.

 

Thanks again 

Avatar

Correct answer by
Level 4

Hi Jorg,

Some solution i found and thought sharing with you all. Let me know if you see any drawback of this approach.

Got a little solution for this after some digging. Sharing for everyone's benefit. Please let me know if you see any drawbacks of this solution.

 

There is a new attribute called "var" introduced in sling 1.3 taglibs. This attribute stores the final output of a component.

Apache Sling - Sling Scripting JSP Taglib

 

CQ 5.6.1 has sling tablib 1.0 so you will need to upload version sling taglib jar 1.3. You can download same from below link

http://repo1.maven.org/maven2/org/apache/sling/org.apache.sling.scripting.jsp.taglib/2.2.0/org.apache.sling.scripting.js…

 

You can just upload via felix console. Below is forum discussion around same

jsp - Using Sling Taglib version 1.3 in a CQ5.6.1 project - Stack Overflow

 

Now in yor JSP you will have to include this new taglib

<%@taglib prefix="sling1" uri="http://sling.apache.org/taglibs/sling"%>

 

and then do the <sling:include> with "var" attribute

<sling1:include path="/etc/designs/mysite/jcr:content/header.html" var="brandNavDiv"/>

 

and then you can read the "var" using pageContext

(String)pageContext.getAttribute("brandNavDiv"));

 

Remember CQ5.6.1 uses sling taglib version 1.0 so if you include /lib/foundation/global.jsp (which has version 1.0 then it will conflict ) then it will conflict.

 

 

Below is complete JSP code

---------------------------------------------------------------------------------

<%@ page import="org.apache.sling.commons.json.io.*,com.adobe.cq.*" %>

<%@ page import="org.apache.sling.engine.*" %>

<%@taglib prefix="sling1" uri="http://sling.apache.org/taglibs/sling"%>

<sling1:defineObjects />

 

<%

  response.setContentType("application/json");

%>

 

<sling1:include path="/etc/designs/mysite/jcr:content/header.html" var="headerDiv"/>

 

<%

response.setContentType("application/json");

JSONWriter writer = new JSONWriter(response.getWriter());

writer.object();

writer.key("header");

writer.value((String)pageContext.getAttribute("headerDiv"));

writer.endObject();

%>

=====================================================

 

copy paste from documentation page

=======================================================================================

sling:include

Includes a resource rendering into the current page.

  • Attributes
    • flush - Whether to flush the output before including the target.
    • resource - The resource object to include in the current request processing. Either resource or path must be specified. If both are specified, the resource takes precedences.
    • path - The path to the resource object to include in the current request processing. If this path is relative it is appended to the path of the current resource whose script is including the given resource. Either resource or path must be specified. If both are specified, the resource takes precedences.
    • resourceType - The resource type of a resource to include. If the resource to be included is specified with the path attribute, which cannot be resolved to a resource, the tag may create a synthetic resource object out of the path and this resource type. If the resource type is set the path must be the exact path to a resource object. That is, adding parameters, selectors and extensions to the path is not supported if the resource type is set.
    • replaceSelectors - When dispatching, replace selectors by the value provided by this option.
    • addSelectors - When dispatching, add the value provided by this option to the selectors.
    • replaceSuffix - When dispatching, replace the suffix by the value provided by this option.
    • scope - If var is specified, what scope to store the variable in. (Since 1.3)
    • var - ariable name to store the resulting markup into (Since 1.3)
  • Since: 1.0

=====================================================================================================

Avatar

Employee Advisor

Hi,

hm, I wasn't aware of this extension. If it works for you, that's fine :-)

kind regards,
Jörg

Avatar

Level 4

Hi Jorg,

Also got info from one user (Vineet Kumar) that we can use <c:import> too. This way we do not need to include new version of sling taglib. Tested the same and its working for me.

<c:import var="headerDiv" url="/etc/designs/en_GB/jcr:content/header.html"/>

<%
    response.setContentType("application/json"); 
%>

<%
JSONWriter writer = new JSONWriter(response.getWriter());
writer.object();
writer.key("headerDiv");
writer.value((String)pageContext.getAttribute("headerDiv"));
writer.endObject();
%>

Thanks again.