Expand my Community achievements bar.

July 31st AEM Gems Webinar: Elevate your AEM development to master the integration of private GitHub repositories within AEM Cloud Manager.
SOLVED

Asynchronous component interactions in AEM

Avatar

Level 3

Hi Folks ,

  Just wondering to see  the best approach to achieve asynchronous component interactions in CQ5  ?  

Lets consider an use case  in which  a custom tabbed component is used .  The tabbed component simply renders tabs with parsys where author can drag and drop some custom components in each tab . The custom components in the tab will make some service calls  . What I would like to achieve is that on  click or selection of  tab ,  the component under the tab should make an asynchronous service call to render itself  , Not on page refresh . I can achieve this functionality by controlling the CSS to show or hide div's but I believe it wouldn't be a optimal and good approach .  

Another use case can be lets say 'AddtoCart' component and 'CartSummary' components are on same page and on asynchronous add to cart action    cart summary should get updated  . 

Can a state change form one component trigger some events that other components can listen to and update asynchronously ? 

Thanks in advance

1 Accepted Solution

Avatar

Correct answer by
Level 1

You might try setting up your tabs so that the tab parsys content is not rendered when in "preview" or "disabled" mode: 

if (WCMMode.fromRequest(request) != WCMMode.DISABLED) {%> <cq:include path="tabChildren" resourceType="foundation/components/parsys" /><%}%>

You'll then have to feed the tab the paths of the parsys content and ajax in the html. You can do something like this to collect the paths for each tab: 

Resource tabChildren = resource.getChild("tabChildren"); Iterator<Resource> tabChilrenIterator = tabChildren.listChildren();
while (tabChilrenIterator.hasNext()) {
String childResourcePath = tabChilrenIterator.next().getPath() + ".html";

//Feed childResourcePath to the tab javascript somehow

}

Then on the front-end in the js tab controller you can ajax in the rendered content:

(assuming that the paths are being set via a javascript array and you're using jQuery)

for (var i = 0; i < paths.length; i++) { $.get( paths[i], function( data ) { $( "#tabContainer" ).append(data); }); }

Something similar could be used for a cart example: an Add to Cart function sends some data to CQ, cq then returns updated cart html, or a json feed. 

 

along with the links smacdonald2008 shared you might also check out: 

http://scottsdigitalcommunity.blogspot.ca/2013/07/using-ajax-requests-to-display-adobe-cq.html

Hope this helps

-Craig

 

View solution in original post

7 Replies

Avatar

Correct answer by
Level 1

You might try setting up your tabs so that the tab parsys content is not rendered when in "preview" or "disabled" mode: 

if (WCMMode.fromRequest(request) != WCMMode.DISABLED) {%> <cq:include path="tabChildren" resourceType="foundation/components/parsys" /><%}%>

You'll then have to feed the tab the paths of the parsys content and ajax in the html. You can do something like this to collect the paths for each tab: 

Resource tabChildren = resource.getChild("tabChildren"); Iterator<Resource> tabChilrenIterator = tabChildren.listChildren();
while (tabChilrenIterator.hasNext()) {
String childResourcePath = tabChilrenIterator.next().getPath() + ".html";

//Feed childResourcePath to the tab javascript somehow

}

Then on the front-end in the js tab controller you can ajax in the rendered content:

(assuming that the paths are being set via a javascript array and you're using jQuery)

for (var i = 0; i < paths.length; i++) { $.get( paths[i], function( data ) { $( "#tabContainer" ).append(data); }); }

Something similar could be used for a cart example: an Add to Cart function sends some data to CQ, cq then returns updated cart html, or a json feed. 

 

along with the links smacdonald2008 shared you might also check out: 

http://scottsdigitalcommunity.blogspot.ca/2013/07/using-ajax-requests-to-display-adobe-cq.html

Hope this helps

-Craig

 

Avatar

Level 10

This subject is currently beyond the scope of the AEM documentation. However - here is a community article that may help:

http://labs.sixdimensions.com/blog/mat-sam/2013-09-16/using-ajax-cq-components

Here is another piece of content that may help as well:

http://felix.apache.org/site/event-admin-handlers.html

Hope this community article helps you. 

Avatar

Level 3

Hi , 

  Thanks for your pointers . Though may not suit in this cases but very useful information to know . 

 

regards

Avatar

Level 3

Hi ,

  Thanks for the information on the approach to be followed . Appreciate it .  

Do you think , following this approach for components other than tabs may require a bit of hard coding ? . Like for example , on  AddToCart action  I might need to know what other components on the page that need to be updated , execute their respective paths asynchronously  and append to their respective div's . 

   

regards

Avatar

Level 7

Sounds like the usage of backbone.js in combination with AEM would be a great idea here IMO.

This could solve the update problems that you are thinking about with and MVC kind of thinking and special event handlings.

Good Luck
/Johan
 

Avatar

Level 1

I agree with Ojjis, it sounds like some sort of structure is needed for your application. Backbone is great, Angular is another great option. Both integrate well with jQuery. Depending on your needs something as simple as a simple pub/sub system to relay messages across your application might be what you need. I have used the tiny-pub-sub in a couple of applications with good results. 

https://github.com/cowboy/jquery-tiny-pubsub

it's really simple and really small:

$.subscribe('foo', function(event, data){ conosle.log(data); }); $.publish('foo', [1, 2]);

 

If you are using Backbone you could create a dispatcher just by extending the event object: 

var dispatcher = _.clone(Backbone.Events);

Then it would just be a matter of setting up your events:

dispatcher.on('foo', function(data) { console.log(data); }) dispatcher.trigger('foo', [1,2]);

Avatar

Level 3

I have personally never used Backbone or Angular but hearing from what you say it seems to be the right fit for my use case . Thanks once again guys .  I will go ahead and implement with your suggested approaches. ..

regards