12 Dec Static and dynamic dialogs in Adobe CQ5
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<selection jcr:primaryType="cq:Widget" fieldLabel="Selection example" fieldDescription="Please select" name="./selection" type="select" xtype="selection"> <options jcr:primaryType="cq:WidgetCollection"> <option1 jcr:primaryType="nt:unstructured" text="Value1" value="value1"/> <option2 jcr:primaryType="nt:unstructured" text="Value2" value="value2"/> <option3 jcr:primaryType="nt:unstructured" text="Value3" value="value3"/> </options> </selection> |
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.
1 2 3 4 5 6 7 |
<selection jcr:primaryType="cq:Widget" fieldLabel="Selection example" fieldDescription="Please select" name="./selection" type="select" xtype="selection" options="/bin/dynamicdialog/options.json" /> |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
package com.example.cq.components.dynamicdialog; import java.io.IOException; import javax.servlet.ServletException; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.SlingSafeMethodsServlet; import org.apache.sling.commons.json.JSONException; import org.apache.sling.commons.json.io.JSONWriter; @Service @Component @Property(name = "sling.servlet.paths", value = "/bin/dynamicdialog/options") public class OptionsServlet extends SlingSafeMethodsServlet { @Override protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); JSONWriter writer = new JSONWriter(response.getWriter()); try { /** * [ { "text":"Test1" }, { "text":"Test2" } ] */ writer.array(); writer.object(); writer.key("text").value("Value1"); writer.key("value").value("value1"); writer.endObject(); writer.object(); writer.key("text").value("Value2"); writer.key("value").value("value2"); writer.endObject(); writer.object(); writer.key("text").value("Value3");</pre> writer.key("value").value("value3");</pre> writer.endObject(); writer.endArray(); } catch (JSONException e) { e.printStackTrace(); } } } |
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!
Anonymous
Posted at 21:26h, 12 Decembergreat job!!
sas.
albertoalmagro
Posted at 12:20h, 13 DecemberThank you sas!
Anonymous
Posted at 17:58h, 20 MarchVery 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))) }
albertoalmagro
Posted at 17:13h, 21 MarchHi Anonymous,
thanks! I appreciate your feedback, I have to try that.
Sabarno Mondal
Posted at 11:13h, 15 JanuaryHi,
Is there any way to create a tab dynamically in a dialog in cq5.please let me know it that's possible or not .
Thanks in advance .
albertoalmagro
Posted at 08:46h, 18 JanuaryHi 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
AJAY BHATT
Posted at 16:44h, 26 JanuaryHi,
Can u please tell me how to access value of selectionchanged event in select xtype. in dialog listener like beforeSubmit
albertoalmagro
Posted at 07:53h, 07 FebruaryHi AJAY,
when you invoke a listener some objects are always passed to it, take a look at http://dev.day.com/docs/en/cq/current/widgets-api/ , search for the selectionChanged listener of your component and see which objects are passed to it. Then you will be able to navigate and find what you want. Regards.
Alisneaky
Posted at 03:46h, 24 Aprilhi 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.
albertoalmagro
Posted at 14:57h, 24 AprilHi 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
mamsha
Posted at 12:48h, 02 JuneHi I got the dropdown , but after selecting dropdown value, its not geting stored in crxde
mamsha
Posted at 12:49h, 02 JuneThanks for the replay in advance
Julien Griffon
Posted at 14:27h, 25 JulyHi,
I got exactly the same bug.
Nothing is stored.
Did you fing a issue ?
Julien Griffon
Posted at 14:42h, 25 JulyHi,
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.
albertoalmagro
Posted at 09:33h, 26 JulyThank you Julien for your correction and for reading my blog, I'm going to change it now!
albertoalmagro
Posted at 18:04h, 02 JuneHi 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!!!
mamsha
Posted at 05:55h, 03 JuneHi Alberto, Thanks for the reply, but its still not getting stored
albertoalmagro
Posted at 14:37h, 04 JuneHi,
it is working for me, if you want I can export it as a component and send it to you, so you can compare and see what's wrong.
Ankur Chauhan
Posted at 05:28h, 10 Junevery Nicely explained….
Thanks a lot……
Julien Griffon
Posted at 15:04h, 25 JulyFinaly works perfectly, Thanks a lot Alberto for this article !
Nitin Tyagi
Posted at 08:09h, 31 JulyHi 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
Srikanth Pogula
Posted at 12:56h, 20 AprilHi 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}