AEM part2

Read our recommendations how to Build Complex Components with AEM Authoring Toolkit

In Part I, we spoke of difficulties that arise when you deal with complex legacy AEM components that continue to grow. Such components need refactoring before they get overwhelmed by their numerous features, bugs and fixes. This may, however, feel like pain itself, especially as it comes to matters of changing or retaining component design and user experience. Luckily we have the AEM Authoring Toolkit and its DependsOn feature that help to reorganize legacy code in an unobtrusive manner. We’ve shown some techniques; you can find many more in our previous articles or in the manual on GitHub.

In Part I, we managed to refactor the complicated Swiss Army Knife component and its authoring dialog so that it does not look messy anymore, all of its facilities distributed between tabs. There’s still room for improvement, though. We have many tabs now, and a user can still get lost among them. The settings are better organized but still live in more or less the same “box.” The verification and processing routines attached to them can easily entangle things all over again. It’s much like headphone wires in your pocket; right now they are alright. Then you stick keys or a coin in there, too and… here we go again.

The question of thorough decomposition is: whenever we have a component that can operate differently depending on settings, wouldn’t it be more natural if a user selected the “operating mode” first and then dealt only with settings for this particular mode?

When we use our Swiss Army Knife, we can convert checkboxes like this tool can cut, can saw, or can open into a single selection that answers the question — what do we want this particular instance to do? Then we can show the “details” tab referring to the selected mode and hide the rest of the tabs. The Toolkit’s @DependsOnTab is intended for this exact process.


In the picture, we’ve just modified the “heading” part of our class and declared another field named mode (see yellow frames). We also made sure that every one of the fieldsets is assigned a name prefix. This way, the author can switch between modes back and forth and save different values, and they will all be preserved in corresponding “subfolders.”
There’s only one complication left. It comes from Java-to-markup integration. Your Java class is probably a Sling model used within an HTL file, so you will have to make each of the fieldset classes, like KnifeFeature or ScissorsFeature, a model in its turn and make sure they are properly injected. This may be not that easy. You will also need to change your HTL calls from ${component.openItems} to something like ${component.openerFeatureHandler.openItems}, which doesn’t read the best.

There’s a way to make the decomposition true and complete. Imagine your Swiss Army Knife as just a facade component that bears the main property – the mode. Imagine then, that the value of mode is nothing but a fully-qualified name of a feature set/fieldset class which now stands as a component back end in its own right.

The “mode” classes can be developed separately and include complicated injection and processing logic. It’s better to make them implement a common interface that would enumerate methods called from HTL to make sure they always return values.

Now we make sure that our OpenerFeature exposed some useful logic like:

And modify our HTL markup like this:

For the “facade” class, the modes would stand as fieldsets and would build up to the common authoring dialog. But for HTL, the modes would each represent a (nearly) independent Java back-end component. They can be processed uniformly or in separate data-sly-test branches and passed to subsidiary templates, etc. No sophisticated nested method calls!


What do we end up with? One component facade with a single resource type, one common but forking authoring experience, many atomic “worker” components behind the scenes, greater code modularity, and better style.

Can you believe we once had a component with 31 widgets in just one dialog? After we used DependsOn and distributed all of them in tabs and aligned them by function, it felt like getting the house clean and orderly for the holidays. Isn’t that nice?

Author: Stepan Miakchilo

How can we help you?
Contact Us