In a selection widget there are two ways to provide the available options, dynamic or static. In the following lines we will discuss how to use them and when.

Static options

They are used when the the options are always the same. Making them static will result in a faster response and better performance of our dialog, but once written, we will not be able to change them. Here is how to do it.

In the selection widget example above, we create directly an array in the dialog’s XML code, providing the text to display and the value to save in JCR. But what happens if the options are not always the same?

Dynamic options

If for some reason we have to calculate our options based on some parameters, or this options depend on the content, it would be interesting to have a mechanism to generate them. This mechanism is known as dynamic options.
To generate the options we will use a Java Servlet. This Servlet can be also developed in JavaScript or we can even develop a JavaScript function, but I prefer to left JavaScript for client side validation. Lets see how the code would look like.

First of all in the dialog’s XML instead of having a static options array we have a Servlet path, in which we could also pass parameters in a RESTful way to process them latter in our Servlet.

For the Servlet we extend the SlingSafeMethodsServlet class. We provide the path with the annotation “property” giving as name “sling.servlet.paths” and as value the same path provided in the dialog XML file. The communication will be done, as we ask in the dialog’s path, in JSON format, so it is necessary to set the content type of the Servlet’s response and write the response in a JSON format. In this example, for simplicity, we create a JSON object with the class JSONWriter, with fixed options only to show how it is done, but in a real environment we would take advantage of Java’s possibilities to generate the options dynamically based on our needs. To finish this post, clarify that what you put under “text” is what will be displayed on your dialog and what you put under “value” is what will be saved in CRX.
I hope this post was useful to you, if you have questions or suggestions just let me know. Thanks!

22 Responses

  1. Very nice feature!
    For similar result, it is possible to use optionProvider under xtype=selection , in this case
    optionProvider=function(path, record){var st='/bin/dynamicdialog/options.json'+(new Date().getTime()); return CQ.Util.formatData(CQ.HTTP.eval(CQ.HTTP.noCaching(st))) }

  2. Hi Sabarno, yes you can, try to execute a JavaScript function in a widget event and within this function execute the .enable() or disable() function of your tab.

    Regards,
    Alberto

  3. hi Alberto,

    Thanks for your great examples. I'm very new to CQ5 and have made some basic components so far. I have not as yet created any with actual Java packages and classes. Generally they've just been using JSP's.

    With this example, where do you actually put the Servlet? Could you give a contextual diagram of the folder structure for this to work please?

    Thanks in advance.

    1. Hi Alisneaky!

      as you can see in the code, I placed it at the same package as the sample component "com.example.cq.components.dynamicdialog". With that you have to figure out that it would be a package for all the components "com.example.cq.components" and inside of it you would find the component, in this case I named it "dynamicdialog".

      For the Server registration I registered it via path at "/bin/dynamicdialog/options but you could register it in any other path based maybe on your architectural design

      To register it as path you would need:
      @Property(name = "sling.servlet.paths", value = "/bin/dynamicdialog/options")

      There are other ways to register a servlet in Adobe AEM depending on your needs. But in this case I would do it definitely by path. Here you can find more information about this topic: https://sling.apache.org/old-stuff/servlet-resolution.html

    1. Hi,
      I found the solution :

      writer.object();
      writer.key("text").value( value );
      writer.key("value").value( key ); // value escaped
      writer.endObject();

      Set only "text" does not fix the value.

  4. Hi Mamsha, yep, there is a bug in the code I posted, instead of name = .selection I should have written name = ./selection. I will correct it now. Thanks!!!

  5. Hi Alberto,

    Nice Explanation. Is there a way by which we can the default value of the selection from the dynamically generated list. For eg I would to set value1 as default for the example given above, but don't want to hard code it using defaultValue as it dynamically generated list.

    Thanks
    Nitin

  6. Hi Alberto,
    Can we pass the author entered value for another field(in the same dialog where the dropdown exists) as a parameter to the servlet invoked to fetch JSON response?
    Something similar to this
    options="/bin/dynamicdialog/options.json?q="${param}