- Andrew Kos
- Bill Burlein
- Bryan Williams
- Christian Vozar
- Jeff Brown
- John Kraus
- Joseph Mak
- Josh Durbin
- Mark Daugherty
- Matt Van Bergen
- Melissa Geoffrion
- Michael Kang
- Michael Chan
- Michael Hodgdon
- Mike Motherway
- Molly McDaniel
- Nadia Maciulis
- Pat McLoughlin
- Paul Michelotti
- Puru Hemnani
- Rohit Srinath
- Ryan Lunka
- Tom Kelly
Limitations of the CQ Parsys Model and the Implementation of a Nested Paragraph System
Monday, February 25, 2013
On my latest project, we had a requirement for creating two layout control components: columns and tabs. In the implementation of these components, we quickly found out CQ is built with the rigid assumption that paragraph systems will never be nested. We wanted the visual layout power and control of allowed components offered by paragraph systems in our layout components, so we had to include nested paragraph systems in our column and tab implementations.
CQ's one-level paragraph system assumption is apparent in the implementation of the out of the box column control and reference components.
The column control component prevents the author from nesting additional column control components. This design decision prevents the author from creating more complex layouts where a site might need columns within columns. Additionally, the time required to set up proper styles for these columns is steep and there is a limited number of layouts that come with CQ.
The reference component will only search for components on the first level within the main paragraph system of a page; no traveling deeper into the tree to search through any nested paragraph systems. Some patch up of this component was necessary to allow it to dig into any nested paragraph systems we might have.
With these limitations in mind, I set off to create a new nestable paragraph system that could overcome these issues.
To start, I created a new component, called “innerParsys”, which acts as a container for the new paragraph system. Within this component, I put a node for the new paragraph system called parsys, which mirrors the construction of the parsys that comes with CQ.
The cellSearchPathModifier function takes in the constructor for a component—which in this case is the custom paragraph system—and modifies the query for allowed components. This function called on render event, which is registered in the editConfig for innerParsys/parsys and innerParsys/parsys/new. Now, since the render event is fired very early on, we have control over what is passed into the function that has the potential to lock up the browser.
With this render function, two nifty things are accomplished:
- Nesting innerParsys will no longer lock up the browser searching for allowed components- a problem with nesting the out of the box parsys
- Allowed components in design mode for the top level paragraph system will propagate to all children, preventing authors from having to edit the design of every child parsys
Since this listener will not be called in design mode, another fix is needed to prevent the authoring environment from locking up the browser in design mode. To accomplish this, innerParsys.jsp wraps the cq:include of the innerParsys/parsys component in an if statement that disables design mode for the paragraph system.
With this temporary disable of design mode, two more nifty things are accomplished:
- Nesting innerParsys will not lock up the browser in design mode
- Authoring nested paragraph systems is simplified by not showing edit bars in design mode since designs are inherited from the parent anyways
Now we have the ability to include innerParsys anywhere the power of a paragraph system is needed inside of a component and that component can be safely placed inside of any other paragraph system.
On our project, innerParsys was used to create a much simpler and more powerful column component and a new tab component.
An example of the code described is available in this gist: https://gist.github.com/kand/4999238
After many hours of looking at stack traces and request logs, one more issue was discovered with nested paragraph systems that caused a slowdown on the server side. While this slowdown is not particularly significant, it is noticeable in some edge cases.
To fix this issue, I took a somewhat hackish approach. First, I pulled the parsys.jsp file into the innerParsys/parsys folder to override the parsys in the CQ libs. Now that I have control over the JSP file contents, I simply replaced the “if” statement that was making the call “if(currentStyle.get(“drawAnchors”, false))” with “if(false)” so this expensive function never runs.
My approach removes the “drawAnchor” functionality from nested paragraph systems, but this is not accessible without the edit bar and the anchor id approach is outdated, regardless. You may want to take a different approach depending on requirements.
I’ve updated the gist to include this change.
In developing a nested paragraph system it has become apparent to me that the CQ design/style concept for paragraph systems needs some serious reworking. It is rife with slow functions and inefficient methodologies.
- Descriptive JMX Beans in AEM/CQ
- Invisible requirements within Business requirements
- Building a better Options Predicate
- Extensionless URLs with Adobe Experience Manager
- The Life of a Tester in Adobe CQ World!
- Limitations of the CQ Parsys Model and the Implementation of a Nested Paragraph System
- Using Apache FOP to generate a PDF document based on a form submission data
- Configuring SAML in AEM 5.6