Goal
Add two Granite Select widgets - /libs/granite/ui/components/foundation/form/select with listeners, each listening to the select event of other. In this sample, Country Select widget and Capital Select widget are fed with data sources, countries and capitals respectively for options, selecting country changes capital, vice versa
Demo | Package Install
Solution
1) Login to CRXDE Lite, create folder (nt:folder) /apps/touchui-select-listener
2) Create clientlib (type cq:ClientLibraryFolder) /apps/touchui-select-listener/clientlib, set a property categories of String type to cq.authoring.dialog and dependencies of type String[] to underscore
3) Create file ( type nt:file ) /apps/touchui-select-listener/clientlib/js.txt, add the following
listener.js
4) Create file ( type nt:file ) /apps/touchui-select-listener/clientlib/listener.js, add the following code
(function ($, $document) { "use strict"; var COUNTRY = "./country", CAPITAL = "./capital"; function adjustLayoutHeight(){ //with only two selects, the second select drop down is not visible when expanded, so adjust the layout height //fixedcolumns i guess doesn't support property height, so fallback to jquery //http://docs.adobe.com/docs/en/aem/6-0/develop/ref/granite-ui/api/jcr_root/libs/granite/ui/components/foundation/layouts/fixedcolumns/index.html $(".coral-FixedColumn-column").css("height", "18rem"); } $document.on("dialog-ready", function() { adjustLayoutHeight(); //get the country widget var country = new CUI.Select({ element: $("[name='" + COUNTRY +"']").closest(".coral-Select") }); //get the capital widget var capital = new CUI.Select({ element: $("[name='" + CAPITAL +"']").closest(".coral-Select") }); if(_.isEmpty(country) || _.isEmpty(capital)){ return; } //workaround to remove the options getting added twice, using CUI.Select() country._selectList.children().not("[role='option']").remove(); capital._selectList.children().not("[role='option']").remove(); //listener on country select country._selectList.on('selected.select', function(event){ //select country's capital and throw change event for touchui to update ui capital._select.val(event.selectedValue).trigger('change'); }); //listener on capital select capital._selectList.on('selected.select', function(event){ //select capital's country and throw change event for touchui to update ui country._select.val(event.selectedValue).trigger('change'); }); }); })($, $(document));
5) Create a simple datasource for countries - /apps/touchui-select-listener/datasource/country/country.jsp
<%@include file="/libs/granite/ui/global.jsp"%> <%@ page import="com.adobe.granite.ui.components.ds.DataSource" %> <%@ page import="com.adobe.granite.ui.components.ds.ValueMapResource" %> <%@ page import="java.util.HashMap" %> <%@ page import="org.apache.sling.api.wrappers.ValueMapDecorator" %> <%@ page import="com.adobe.granite.ui.components.ds.SimpleDataSource" %> <%@ page import="org.apache.commons.collections.iterators.TransformIterator" %> <%@ page import="java.util.Map" %> <%@ page import="java.util.LinkedHashMap" %> <%@ page import="org.apache.commons.collections.Transformer" %> <%@ page import="org.apache.sling.api.resource.*" %> <% final Map<String, String> countries = new LinkedHashMap<String, String>(); countries.put("INDIA", "India"); countries.put("USA", "United States"); countries.put("CHINA", "China"); final ResourceResolver resolver = resourceResolver; DataSource ds = new SimpleDataSource(new TransformIterator(countries.keySet().iterator(), new Transformer() { public Object transform(Object o) { String country = (String) o; ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>()); vm.put("value", country); vm.put("text", countries.get(country)); return new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm); } })); request.setAttribute(DataSource.class.getName(), ds); %>
6) Create datasource for capitals - /apps/touchui-select-listener/datasource/capital/capital.jsp
<%@include file="/libs/granite/ui/global.jsp"%> <%@ page import="com.adobe.granite.ui.components.ds.DataSource" %> <%@ page import="com.adobe.granite.ui.components.ds.ValueMapResource" %> <%@ page import="java.util.HashMap" %> <%@ page import="org.apache.sling.api.wrappers.ValueMapDecorator" %> <%@ page import="com.adobe.granite.ui.components.ds.SimpleDataSource" %> <%@ page import="org.apache.commons.collections.iterators.TransformIterator" %> <%@ page import="java.util.Map" %> <%@ page import="java.util.LinkedHashMap" %> <%@ page import="org.apache.commons.collections.Transformer" %> <%@ page import="org.apache.sling.api.resource.*" %> <% final Map<String, String> capitals = new LinkedHashMap<String, String>(); capitals.put("INDIA", "New Delhi"); capitals.put("USA", "Washington DC"); capitals.put("CHINA", "Beijing"); final ResourceResolver resolver = resourceResolver; DataSource ds = new SimpleDataSource(new TransformIterator(capitals.keySet().iterator(), new Transformer() { public Object transform(Object o) { String capital = (String) o; ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>()); vm.put("value", capital); vm.put("text", capitals.get(capital)); return new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm); } })); request.setAttribute(DataSource.class.getName(), ds); %>
7) The Touch UI dialog xml - /apps/touchui-select-listener/sample-select-listener/cq:dialog
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" jcr:title="Multifield TouchUI Component" sling:resourceType="cq/gui/components/authoring/dialog" helpPath="en/cq/current/wcm/default_components.html#Text"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <fieldset jcr:primaryType="nt:unstructured" jcr:title="Sample Select" sling:resourceType="granite/ui/components/foundation/form/fieldset"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <country jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/select" fieldLabel="Country" name="./country"> <datasource jcr:primaryType="nt:unstructured" sling:resourceType="/apps/touchui-select-listener/datasource/country" addNone="{Boolean}true"/> </country> <capital jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/select" disabled="{Boolean}false" fieldLabel="Capital" name="./capital"> <datasource jcr:primaryType="nt:unstructured" sling:resourceType="/apps/touchui-select-listener/datasource/capital" addNone="{Boolean}true"/> </capital> </items> </column> </items> </fieldset> </items> </column> </items> </content> </jcr:root>
8) The component structure in CRXDE Lite
Hi,
ReplyDeleteI hope you reply to this.
You mentioned above--->
//listener on country select
country._selectList.on('selected.select', function(event){
//select country's capital and throw change event for touchui to update ui
capital._select.val(event.selectedValue).trigger('change');
});
I need a similar function for a checkbox, to check if that checkbox is checked or unchecked. If it is checked, I should hide a tab.
Please help.
Raja
hello raja, is simple jquery call not working? for example to check if the checkbox is checked (assuming there is only one checkbox in dialog) - $(".cq-dialog-content").find(":checkbox").prop("checked") == true
DeleteI have a json which will have multifield data .Suppose i have 2 records For each record content is rich text in this json when i am reopening the touch ui dialog all the values are getting filled from json except the rich text(content) for each record .Is there any solution?.
ReplyDeleteHi, can you upload the component/dialog package and share url here for better understanding?
Deletehttps://drive.google.com/file/d/0B3-hSBVuj2wpZkdYelJuY3dvUXc/view?usp=sharing
DeleteTry this one https://drive.google.com/file/d/0B3-hSBVuj2wpLU5IVTdIYXpiU1U/view?usp=sharing
DeleteThe component doesn't get added in par or rendered, but i think i understand what you are saying.. check this post http://experience-aem.blogspot.com/2015/07/aem-61-touch-ui-composite-multifield-with-rich-text-editor-rte.html
DeleteHi,
ReplyDeleteis there a way to sort alphabetically the collection ?
ITEM._selectList.on('selected.select', function(event), This event is not being triggered in 6.2 with /libs/granite/ui/components/coral/foundation/form/select. can someone point how we can handle on selection change
ReplyDeleteDid you get a solution for this? If so can you please share? Thanks
DeleteHi, Thanks for the great post!!, I am getting the following warning...An instance of Select is already attached to the specified target element. Future versions of CoralUI will throw an exception at this point.
ReplyDelete