AEM 61 - TouchUI Add Items to Multifield based on Select (Drop Down) value

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>

1 comment:

  1. Should use a servlet not JSP. Use @Property(name = "sling.servlet.resourceTypes", value = { /path/to/use }

    ReplyDelete