Dynamically Populate Select Options in AEM Component Dialog

Published
Creating dynamic and interactive components can significantly enhance the authoring experience. One effective enhancement is dynamically populating the options of a select field within a component dialog. This is especially useful when the options need to be fetched from an external source or depend on other selections made by the author.

Using ACS AEM Commons

For a select list that needs regular updates with new items, you can use the Generic Lists utility from ACS AEM Commons to make changes without code deployment. Generic Lists allow for the easy creation and management of simple key-value pairs. Check out this article on how to install ACS AEM Commons.
To create Generic Lists, navigate to Tools > ACS AEM Commons > Generic Lists and click on Create. Generic Lists are represented as CQ Page under /etc/acs-commons/lists.
ACS Commons Generic List
Once the list is created, you have the option to edit it and add values. Click Add to add items to list, use drag handles to re-order items.
ACS Commons Generic List Items
Using datasource, Generic List items can be loaded into select lists. To achieve this, Generic List-specific datasource can be used.
article / _cq_dialog / .content.xml
<articleTypes jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/select" fieldLabel="Article Types" name="./articleTypes"> <datasource jcr:primaryType="nt:unstructured" sling:resourceType="acs-commons/components/utilities/genericlist/datasource" path="/etc/acs-commons/lists/article-types" /> </articleTypes>
In the component dialog, it will appear as shown below.
Component Dialog using Generic List
To update the select list options, choose the specified list from the Generic Lists and click on Properties. The changes will be reflected in the component dialog immediately.

Using Sling Servlet

In some cases, select options need to be retrieved from an external source or other component properties, which can be accomplished using custom servlet. To utilize the custom servlet, the component dialog XML will look like the example below.
article / _cq_dialog / .content.xml
<articleTypes jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/select" fieldLabel="Article Types" name="./articleTypes"> <datasource jcr:primaryType="nt:unstructured" types="articleTypes" sling:resourceType="/bin/public/aem-demo/dropdowns"/> </articleTypes>
You can pass properties from the component dialog to servlet, similar to how types are passed in the above example.
To populate options for select field using custom servlet, follow the example below and adjust the implementation according to your requirements.
servlets / DropdownServlet.java
@Component(service = { Servlet.class }) @SlingServletPaths( value = "/bin/public/aem-demo/dropdowns" ) @ServiceDescription("Dynamic Dropdown Servlet") public class DropdownServlet extends SlingSafeMethodsServlet { @Reference DropdownService dropdownService; @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) { ResourceResolver resolver = request.getResourceResolver(); // Current Page Path String currentPagePath = request.getRequestPathInfo().getSuffix(); // Fetch Property from datasource Resource datasource = request.getResource().getChild("datasource"); ValueMap vm = datasource.getValueMap(); String type = vm.get("types", ""); // articleTypes // Fetch dropdown options from External Source or other Component properties List<String> options = dropdownService.getOptions(currentPagePath, type); DataSource dataSource = new SimpleDataSource( new TransformIterator<>(options.iterator(), input -> { ValueMap valueMap = new ValueMapDecorator(new HashMap<>()); valueMap.put("value", input); valueMap.put("text", input); return new ValueMapResource( resolver, new ResourceMetadata(), JcrConstants.NT_UNSTRUCTURED, valueMap); })); request.setAttribute(DataSource.class.getName(), dataSource); } }
Caffeine (or any caching service) can be used to cache dropdown options, ensuring faster loading times for dialogs. It's essential to implement cache expiration or invalidation to ensure that the latest updates are reflected in the dialog.

References

Write your Comment