In this post, I’ll show you how to easily and cleanly create a dynamic dropdown in an AEM Content Fragment Model driven by an ACS AEM Commons Generic List.
What are Content Fragments?
But first, what are Content Fragments? Content Fragments are a powerful feature in Adobe Experience Manager (AEM) for managing structure content.
Each Content Fragment has a model which defines the structure of the Content Fragment. To edit the model, Adobe provided an editor with common fields, including text fields, number fields, and dropdowns (called Enumerations).
Why isn’t this Out of the Box?
Unfortunately, when Adobe implemented the Content Fragment Model editor, they didn’t consider extensibility. The fields are very limited and there is no API for adding custom fields.
Despite these significant shortcomings, Content Fragments make managing simple content structures effortless, due to their simplicity and ease of use.
While Adobe made it harder for implementors by failing to follow best practices, like using Sling Resource Merger or structuring components in a sane manner, we are using Apache Sling. So, we can “kick it old school” and overlay the component.
Our Mission Statement
The Enumerations field included in Content Fragment Models only supports setting a static set of options. This is good enough for slideware, but in real life, it’s inadequate. A couple problematic use cases include:
- Multiple models sharing the same set of values
- Lists of options where a new options needs to be dynamically added
- Option lists which change their options in the context of where / how the Content Fragment is used
Inspired Digital Experiences for Manufacturing & Automotive
Whether you’re just beginning your digital transformation journey or are well on your way, we invite you to explore our partnership with Adobe and our diverse capabilities in manufacturing and automotive.
To create a dynamic dropdown, we’ll overlay the JSP script used to generate the dropdown options from the static list:
By creating a script at:
Since Sling prioritizes /apps over /libs when it looks up scripts, our script will get called instead of the original script.
The original script is simple; it hackily converts the String of comma-separated options into a com.adobe.granite.ui.components.ds.DataSource object and then sets that as a request object. Pretty easy to reproduce! But of course, we don’t want to break the existing functionality.
To avoid breaking the existing functionality, we can prefix all of our dynamic dropdowns with a known prefix. This will also allow us to even have multiple different types of dropdown population methods.
In this example, we’ll use the prefix: “acs-commons-list:” for populating a dropdown of the values of an ACS AEM Commons Generic List. Additionally, we have to use a Lambda function to map the properties in the Generic List into the format used by the DataSource. All said and done, here’s what the script looks like:
Once we have the script in place, we can use dynamic and static dropdowns together.
With this technique, we are no longer constrained to static dropdowns with AEM Content Fragments. With more prefixes, we can have even more options to populate dynamic dropdowns.
Pretty useful article! I have a question, What if I need two custom data source for the dropdowns but I need to limit the list options of the second depending on the value selected in the first one? How to share that context data between different fields? Thanks
Thanks Dan for the blog. My question is how to make this drop down multi select and store it as a string array.
Theoretically, you could have a similar overlay process, but overlying the main component script, not just the optionrenderer.jsp. This would be pretty custom however, so I’d first think if there’s some other way to structure your data to avoid this setup.
Good question… I’d actually think you’d need to do this via a ClientLib in addition to this extension. Since the script returns the values from the server-side, you can’t have it filter based on the value of another field. You’d have to have a dropdown which has a clientlib attached which dynamically updates it’s values based on the value of the other field.