Goal
In a Touch UI dialog, add items to Multifield dynamically, based on the value selected in Drop Down (Select) widget. In this sample, countries are added in multifield /libs/granite/ui/components/foundation/form/multifield based on the language selected /libs/granite/ui/components/foundation/form/select
Demo | Package Install
Solution
1) Login to CRXDE Lite (http://localhost:4502/crx/de) and create folder /apps/touchui-dynamic-select-multifield
2) Create node /apps/touchui-dynamic-select-multifield/clientlib of type cq:ClientLibraryFolder and add a String property categories with value cq.authoring.dialog
3) Create file (nt:file) /apps/touchui-dynamic-select-multifield/clientlib/js.txt and add
dynamic-multifield.js
4) Create file (nt:file) /apps/touchui-dynamic-select-multifield/clientlib/dynamic-multifield.js and add the following code
(function ($, $document) { "use strict"; var LANGUAGE = "./language", COUNTRY = "./country"; $document.on("dialog-ready", function() { var langCountries = {}, $language = $("[name='" + LANGUAGE + "']"), $countryDelete = $("[name='" + COUNTRY + "@Delete']"), cuiLanguage = $language.closest(".coral-Select").data("select"), cuiCountry = $countryDelete.closest(".coral-Multifield").data("multifield"), $countryAdd = cuiCountry.$element.find(".js-coral-Multifield-add"); cuiLanguage.on('selected.select', function(event){ var $country; cuiCountry.$element.find(".js-coral-Multifield-remove").click(); _.each(langCountries[event.selected], function(country){ $countryAdd.click(); $country = cuiCountry.$element.find("[name='" + COUNTRY + "']:last"); $country.val(country); }); }); function fillCountries(data){ var countries; _.each(data, function(country, code){ if(!_.isObject(country) || (country.country === "*") ){ return; } code = getLangCode(code); countries = langCountries[code] || []; countries.push(country.country); langCountries[code] = countries; }); } $.getJSON("/libs/wcm/core/resources/languages.2.json").done(fillCountries); }); function getLangCode(code){ if(code.indexOf("_") != -1){ code = code.substring(0, code.indexOf("_")); } return code; } })(jQuery, jQuery(document));
5) Create a simple datasource for languages - /apps/touchui-dynamic-select-multifield/datasource/language/language.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> languages = new LinkedHashMap<String, String>(); languages.put("", "Select"); languages.put("ar", "Arabic"); languages.put("en", "English"); languages.put("de", "German"); final ResourceResolver resolver = resourceResolver; DataSource ds = new SimpleDataSource(new TransformIterator(languages.keySet().iterator(), new Transformer() { public Object transform(Object o) { String language = (String) o; ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>()); vm.put("value", language); vm.put("text", languages.get(language)); return new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm); } })); request.setAttribute(DataSource.class.getName(), ds); %>
6) Touch UI dialog xml - /apps/touchui-dynamic-select-multifield/fill-multifield-on-select-component/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="Sample Dynamic Select Multifield 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"> <language jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/select" fieldLabel="Language" name="./language"> <datasource jcr:primaryType="nt:unstructured" sling:resourceType="/apps/touchui-dynamic-select-multifield/datasource/language" addNone="{Boolean}true"/> </language> <country jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/multifield" fieldLabel="Country"> <field jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" name="./country"/> </country> </items> </column> </items> </fieldset> </items> </column> </items> </content> </jcr:root>
Should use a servlet not JSP. Use @Property(name = "sling.servlet.resourceTypes", value = { /path/to/use }
ReplyDelete