'AEM - Refresh datasource after granite field change

I am trying to figure out how to refresh a granite data source for a select field from a pathfield that I will like to also pass into the data source.

Basically:

  1. Set a path (pathToOptions) that will look at a content fragment model

  2. Datasource is called, each time the path value has changed in the dialog, to Sling Servlet to retrieve all fields of content fragment

  3. Author dialog generates options, for granite select drop down (cfOptions), with the fields from the data source.

     <pathToOptions jcr:primaryType="nt:unstructured"
         sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
         fieldLabel="CF Path"
         rootPath="/content"
         name="./pathToOptions"/>
     <cfOptions jcr:primaryType="nt:unstructured"
         sling:resourceType="granite/ui/components/coral/foundation/form/select"
         fieldLabel="CF Options"
         name="./cfOptions">
         <datasource jcr:primaryType="nt:unstructured"
             sling:resourceType="/bin/path/to/servlet"/>
     </resProperties>
    

(Variable names and paths are just generic)

Without so much knowledge of AEM Granite data sources and Apache Sling API; is there a viable method with the data source, or would I need to rely on AJAX. If the latter, i'll post a follow up question.



Solution 1:[1]

After some research; it turns out it is not possible to do this with a datasource, but instead use AJAX ($.ajax()) to communicate with the Sling Servlet to achieve the necessary functionality.

https://helpx.adobe.com/experience-manager/using/creating-touchui-dynamic.html

I used this documentation as a base to do the functionality, but adjusted to my specifications.

(function ($, $document) {
    "use strict";

    var LANGUAGE = "./language", COUNTRY = "./country";

    function adjustLayoutHeight(){
        $(".coral-FixedColumn-column").css("height", "20rem");
    }
 
    $document.on("dialog-ready", function() {
        adjustLayoutHeight();
     
        // Getting reference of language drop down field
        var language = $("[name='" + LANGUAGE +"']").closest(".coral-Select")
     
        // Initializing country drop down field
        var country = new CUI.Select({
            element: $("[name='" + COUNTRY +"']").closest(".coral-Select")
        });
     
        if(_.isEmpty(country) || _.isEmpty(language)){
            return;
        }
     
        var langCountries = {};
     
        country._selectList.children().not("[role='option']").remove();
     
        function fillCountries(selectedLang, selectedCountry){

            var x = $("[name='./country']").closest(".coral- Select").find('option').remove().end();
            _.each(langCountries, function(value, lang) {

                if( (lang.indexOf(selectedLang) !== 0) || (value.country == "*") ){
                    return;
                }

                var test2 = $("[name='./country']")[0];

                $("<option>").appendTo(test2).val(lang).html(value.country);

            });

            country = new CUI.Select({
                element: $("[name='" + COUNTRY +"']").closest(".coral-Select")
            });
         
         
            if(!_.isEmpty(selectedCountry)){             
                country.setValue(selectedCountry);     
            }
         
        }
     
        //listener on language select for dynamically filling the countries on language select
        language.on('selected.select', function(event){
            console.log(event);
            fillCountries(event.selected);
        });
     
        // Get the languages list from the source
        $.getJSON("/libs/wcm/core/resources/languages.2.json").done(function(data){
            langCountries = data;
         
            var $form = country.$element.closest("form");
         
            //get the second select box (country) saved value
            $.getJSON($form.attr("action") + ".json").done(function(data){
                if(_.isEmpty(data)){
                    return;
                }

                // Passing values to populate countries list
                fillCountries(language.val(), data.country);
            })
        });
    });
})($, $(document));

This snippit is originally from the article. I only applied it just in case if the link goes dead. I've seen plenty of Adobe's forum posts having 404 links, so this is added as a precaution for future reference.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ccpizza