Introducing context aware configurations
Example
Let’s say we are in an e–commerce environment for a clothing store with the following content tree:
/content
/clothing-store
/t-shirts
/pants
/sweaters
/jackets
The store has created a new promotion component which consists of an image and some text with information about the promotion. It will be added to all product detail pages throughout the whole website. The component should be the same for T-shirts and sweaters but needs to be different for pants. For jackets, it cannot be there at all since there are no promotions currently active. In a normal scenario this becomes difficult to manage. You could consider creating an experience fragment with different variations, but you would then have to manually add the correct variation to the product pages or write code to dynamically pick the right variation based on the path in AEM. This is where context aware configurations come in.
First off, the component will not read the configuration from its dialog like we are used to, but from the context aware configuration. This makes it so we can add the component to the template and fill it dynamically based on the configuration. There’s no need to add the component on individual pages, making it less work for content authors. As for the configuration, we should start by creating a configuration at /content/clothing-store. This configuration will be applied to all promotion components under this path. Because T-shirts and sweaters should have the same configuration, we will use the image and text for those promotions.
Pants need a different configuration, so we will now create a new configuration at /content/clothing-store/pants. When adding this, you will see that inheritance is enabled and the values from the upper level are already filled in.
We can disable the inheritance and change the values, which will now be applied to all promotion components under this level.
For jackets, we will also create a configuration page, but here we will delete the configuration for the promotion component or make the values empty based on how you’ve set it up. In our overview, we will now not see the configuration anymore.
Let’s compare it with the configurations for pants:
Let’s compare the pages!
Collections
Collections allow you to have multiple configurations for a single component. They are comparable to a multifield from the regular configuration dialog. This does mean that the component needs to have some logic that determines which is the correct configuration to choose from. You could select a configuration based on one of the configured values, or you could pick a random one if that’s what you need.
Let’s go back to our e-commerce store to give you an example. We want to have a custom component that shows a description and some additional information about the material the T-shirt is made of. Every page under /content/clothing-store/t-shirts has a tag configured, like “cotton” or “polyester”. We can now add 2 configurations in which we will select the corresponding tag “cotton” or “polyester”, along with the descriptions and information we would like to show for this material. When adding the component to a t-shirt page it should check if the configured tag is also applied to the page itself. If so, we know which configuration to use for our component.
Context path
A context aware configuration needs to know in which context it should work. This context will always be visible right at the top of your configuration page. As I mentioned before, the configurations will apply to the whole content tree, but it still needs to know where to start from and how to handle underlaying levels. This can be done by setting a context path.
There’s two ways to set a context path:
- Add a @sling:configRef property to each root page for a context’s subtree. This allows you to manually set a context path for all the pages individually.
- Use the sling context aware configuration extensions provided by wcm.io
For most cases in AEM, the second option is the way to go. Wcm.io provides an extensions bundle that is specifically designed for AEM usage and spares you lots of work to individually set context paths to your pages. They also allow you to choose between some different ways of setting the path to match your project’s structure in the best way possible.
The technicals
In AEM, there are two ways to integrate context aware configurations into your project. You can either add a dependency in your POM file, or you can download a package and upload it through your CRX instance.
After installation, you will need to create a new template. You should use the specific resource type that is included in the bundle.
Note that in most projects, you will still need to allow the newly created template in your root pages before you can add it as a page.
Once you have your template, you can start adding your configuration dialogs using an annotation class.
If you would like to work with a collection, simply add “collection = true” to the @Configuration annotation. You can see that some custom widgets can be used, which you can find here: https://wcm.io/caconfig/editor/usage.html
At this point you can add a page using your new template in your AEM site structure and configure your newly created configuration. There are multiple ways to use your configured values in your HTL files. One way is to use them directly is HTL like this:
Alternatively, you can create a sling model that adapts the incoming resource to your custom configuration class:
If you are working with collections, you will need to select the correct config based on one of the values. It could end up looking like this:
To finish off, you will need to set up the context path strategy. Depending on how you want to use context aware configurations, this can change quite a lot from project to project. There is a good guide online that goes through the options you can set and what they mean, so I will not go into detail about that too much in this blog. You can find that guide here: https://wcm.io/caconfig/extensions/context-path-strategies.html
Adding your configuration to one level only
There are cases where you might want to add a configuration only on one level, for example on country level. You could choose to add something to the country page properties, or you can do some custom workarounds in context aware configurations.
The configuration editor bundle which you installed before comes with a class called ConfigurationEditorFilter. This class is used when you edit one of the configurations that matches with the context path pattern regex, which you have configured in the extensions OSGI config. If there’s a match, the “allowAdd” method is called. This method checks which context aware configurations can be added to this location of the content tree. If you override this method in a custom Java file, you can customize this to your liking. Here’s an example:
Useful links
- https://wcm.io/caconfig/
- https://wcm.io/caconfig/editor/
- https://wcm.io/caconfig/extensions/
- https://sling.apache.org/documentation/bundles/context-aware-configuration/context-aware-configuration.html
- https://mvnrepository.com/artifact/io.wcm/io.wcm.caconfig.editor
- https://experienceleague.adobe.com/docs/experience-manager-core-components/using/developing/context-aware-configs.html?lang=en