7 Replies Latest reply on Dec 10, 2012 8:46 AM by orotas

    Pass ClientSide Value to Sling:Include

    Jayatl Level 1



      I have a business requirement to dynamically load content in a page based on the changes of a dropdown list. My client has 100+ pricing elements that would need to be loaded based on the visitor’s selection of a dropdown list. Instead of having my Authors create 100+ separate pages for each pricing element, it seems more efficient to simply create a generic page (with header, footer, content that applies to all pages) and dynamically load the pricing elements somewhere in the page body.


      What I’m struggling to understand is how to pass the visitor’s selection of the dropdown list (JavaScript against the dropdown’s onchange event seems like the most appropriate) to CQ’s sling:include function to load the appropriate CQ page.


      In the dropdown list, I can create the Text | Value pair something like this:


      Content1 | /content/myproject/content1
      Content2 | /content/myproject/content2
      Content3 | /content/myproject/content3


      From there, I’m thinking I would use JavaScript and the dropdown list’s onchange event to get the appropriate page URL value and pass it to “mypage.html” and use the sling:include function to load that content inside of the page body.  My questions are:


      1. How to I pass the client side value (e.g., /content/myproject/content1) to CQ’s sling:include function so that it’s dynamic?
      2. How do I ensure that when mypage.html is loaded, the CQ dispatcher’s caching mechanism doesn’t cache this dynamic content?


      Thanks in advance for any assistance.

        • 1. Re: Pass ClientSide Value to Sling:Include
          Sudharsan S Level 1


          1. Have a sling selector(load.html.jsp) in the page component
          2. Set the selected value in the request scope
          3. After selection render mypage.load.html
          4. load.html.jsp will perform
            • reading and passing the selected value from request to sling:include tag
            • sling:include tag which has static text with dynamic text/value inclusion from request



          • 2. Re: Pass ClientSide Value to Sling:Include
            Jayatl Level 1



            Thank you for the response; however, I'm still a little unclear about how to pass the string to the load.html.jsp from the client side.  Is this using URL Parameters or something else?  if URL parameters, doesn't that mean the the Dispatcher won't cache any of the page content?


            From there, I think I understand what your are suggesting, something like this:


            String contentLoc = [value_from_client];
            <% sling.include(contentLoc) %>


            Am I on the right track?

            • 3. Re: Pass ClientSide Value to Sling:Include
              Ryan Lunka Level 3

              I think you are missing a fundamental piece to this.  A cq:include (or sling:include) is a server-side function.  Basically your JSP is a descriptor for how to output some file - in your case, probably HTML.  The include tag lets you include other JSPs or other resources, so you have flexibility in code.  If you think about how the request-response cycle works, trying to pass a client-side value to an include tag doesn't really work.


              I think your best best for doing this is along the lines of what Sudharsan suggested.  I'm not sure why you would be worried about caching in this scenario.  If I understand you are dynamically loading content based on a user selection.  Caching wouldn't be appropriate, because the state of the HTML (i.e. what content you load in the page) is completely dependent on the user's individual selection.  That is not really a cacheable situation.


              Allow your dropdown selection make a new GET request for the same page with a request paramter that you can access via the JSP.  Then you can use the appropriate server-side resource resolution mechanisms in Sling to output the appropriate content.  There may also be a more complex way that involves AJAX, which enables some of this to be cached.

              • 4. Re: Pass ClientSide Value to Sling:Include
                Sudharsan S Level 1


                As you said above you are having a pricing component which has static content followed by dynamic value based on the pricing option. so have a custom text component and output the static text followed by pricing elements from request scope as like below


                <%=XXX text from component dialog + slingRequest.getAttribute("selectedVal");%>


                Now to render this piece of line, you need to pass/set the selected value to request scope as like below




                then include resource using sling:include tag

                <sling:include path="<path-to-customtextcomp-node>"/>


                As Ryan said, caching dynamic content is not right solution.



                • 5. Re: Pass ClientSide Value to Sling:Include
                  orotas Level 4

                  Well if there are only 100 variations then caching would be the appropriate solution. Just because the content loads based on user choices doesn't mean that caching should be discarded, as long as the number of permutations that result from the user interaction is a reasonable amount caching is still an appropriate solution.


                  The answer to how you communicate client side values to something like cq:include is in the URL. Depending on you use case there are really 3 choices - in the query string, in a post, or via what's called a selector in Sling. Check out there following for a break down of the options within the context of Sling http://dev.day.com/docs/en/cq/current/developing/the_basics.html#URL Decomposition.


                  Now a selector is simply the a string between the end of the path and the extension. It can influence what script Sling uses to respond to a request, but it can also be used to communicate information - like you users selection in the drop down. Within your JSP you simply call slingRequest.getRequestPathInfo().getSelectors() and you are able access the selectors as and Array. So you can code the appropriate components within you template to use the contents of the selector to determine which content to display. If you are trying to include content from another page within the system you might be better off using sling:include instead of cq:include however.


                  Using selector ensure that the requests are cachable and as importantly flushable.


                  Another possiblity is of course to leverage AJAX to get your dynamic data. Depending on how you are storing you data in the repository and whether or not you need unique URLs SEO reasons an AJAX solution might be appropriate.

                  • 6. Re: Pass ClientSide Value to Sling:Include
                    Ryan Lunka Level 3

                    I'm not sure I agree with orotas on that one.  Here's why..


                    I'm assuming pricing-elements are going to be based on content, which means they are fundamentally not static.  They may not change often, but they may change.  I don't know that trying to cache an entire page for each one is appropriate.  If caching is really an issue, I would take the approach similar to how CQ handles personalization.  Cache everything BUT the request-dependent information, then use AJAX to load that part.


                    I also don't feel great about using selectors in lieu of request paramters.  It's possible, but it seems wrong to me.  My understanding of a selector is so that you can retrieve resources in different forms.  For example, maybe you ahve path/to/some/profile.basic.html and path/to/some/profile.extended.html.  You are addressing the same resource, but changing the way it is presented using a selector.  Using a selector to determine the resource you are trying to output (which is effectively what this recommendation suggests) is slightly different, and I think appropriately would require a GET request parameter.

                    • 7. Re: Pass ClientSide Value to Sling:Include
                      orotas Level 4

                      Well there are a lot of things that go into deciding whether or not a piece of data is appropriate for caching. The source of the data and how you know whether or not the data should be flushed is an important consideration. My assumption here was that the data was being managed within the repository and that anytime it changed you'd have an activation event that would trigger a dispatcher flush event. If the data is being managed within the context of the page being rendered then use of a selector ensures that all the cached variations are flushed when when the main page is flushed.


                      I agree that an AJAX request like CQ uses for personalization is an appropriate option for the use case discribed, depending on the SEO requirements. Somthing like a selector is however useful if there is a need to index and make available to Google each of the variations. If SEO isn't a requirement then I'd also lean in the direction of an AJAX request. Depending on how the data is stored in CQ (if it's stored in CQ) then the request may or may not be cachable.


                      If the content is managed within the repository but in another location there are several approches to ensure the content is flushed, depending on the specifics of the application in question. My point was just because content is dynamic based on user selection doesn't mean it can't be cached. There are plenty of situations in which caching isn't appropriate, however there are many options for increasing the level of caching that should be considered.


                      As to the usage of the selectors while using the selectors to control presentation is certianly how Sling leverages the selector, it isn't the only thing that it can be used for. Selectors have traditionally been used to make variations of page content cachable. I would say that from a RESTful principles perspective use of a selector for communicating resource information would be prefereable to a request perspective. Another option would also be to use a suffix but that makes it harder to cache/flush items.


                      I guess in the end I don't think that any of these things are absolutes, I think that you have to consider the specifics of you application but that more stuff is cachable than most people think, so don't give up on caching unless you have considered some of the alternatives.


                      One word of warning about selectors is that you will want to either white list them at the web server layer, or throw a 404 response if the selector isn't valid in order to prevent DDOS attacks filling up your dispatcher cache disk.