Using a Dojo Deferred with asynchronous functions

566
0
04-02-2020 11:29 AM
JustinBridwell2
Occasional Contributor II

I have 2 dropdowns that are created onOpen using Dojo/Dijit Select in my custom Web AppBuilder widget. enter image description here

The first dropdown contains parent projects and the second dropdown contains a list of subprojects related to the currently selected parent project in the first dropdown. To populate each, a query is first made to a REST service, the results are parsed and then entered as a parameter into the function that actually creates the Dojo Select dropdown; Projects first and then subprojects. Here is an example of the Projects workflow, which contains an on('click') event to trigger the second subprojects query and dropdown creation:

Parent Projects:

function createProjectDropdown(items) {    
    // New dropdown for parent projects.
    var projectNode = dom.byId("projectDropdown");
    if (items.length >= 1) {
        var projectsOptions = items.map(projectname => {
            return { "label": projectname, "value": projectname }
         });
    }
    else {
        let current_user = parent.thisWidget.getCurrentUser();
        var projectsOptions = [{ "label": `No projects available to user "${current_user}"`, "value": "Noprojects" }]    }                  // Create project selector dropdown    var projectSelector = new Select({        name: "projectSelect",        id: "projectSelect",        options: projectsOptions     }).placeAt(projectNode).startup();     // This is the on change event that triggers the subprojects dropdown     // change based on the user's input. e = user's selection.    dijit.byId('projectSelect').on('change', function (e) {        var subprojectQuery = new esriQuery();        let username = widgetConfig.userAuthorizationTable.usernameField;        this.currentUser = IdentityManager.credentials[0].userId;        let current_user = this.currentUser;        subprojectQuery.where = `${username} = '${current_user}'`;        var project_name = e         var subprojectsField = widgetConfig.userAuthorizationTable.subprojectsField_1;        subprojectQuery.outFields = [subprojectsField];        var subprojectAccessEndpoint = widgetConfig.subprojectTaskTrackingURL + "/" + widgetConfig.userAuthorizationTable.index;
        var subprojectAccessQueryTask = new QueryTask(subprojectAccessEndpoint);
        subprojectAccessQueryTask.execute(subprojectQuery,
            function (results) {
                let records = results.features;
                if (records.length >= 1) {
                    let subprojects = records[0].attributes[subprojectsField];
                    let subprojects_list = subprojects.split(',');
                    let subprojects_trimmed = subprojects_list.map(item => item.trim());
                    subprojects_trimmed = subprojects_trimmed.sort();
                    // The subprojects dropdown function is called
                    createSubprojectDropdown(subprojects_trimmed);
                    console.log("query result: ", results);
                    thisWidget.loadData(e);
                }
                else {
                    let noSubprojectAccess = [];
                    createSubprojectDropdown(noSubprojectAccess);
                }
            },
            function (error) {
                 console.log("query error: ", error);
            });
    });}

Then the function is called:

var projectAccessEndpoint = widgetConfig.subprojectTaskTrackingURL + "/" + widgetConfig.userAuthorizationTable.index;
var projectAccessQueryTask = new QueryTask(projectAccessEndpoint);
projectAccessQueryTask.execute(projectQuery,
    function (results) {
        let records = results.features;
        if (records.length >= 1) {
            let projects = records[0].attributes[projectsField];
            let projects_list = projects.split(',');
            let projects_trimmed = projects_list.map(item => item.trim())
            createProjectDropdown(projects_trimmed);// The projects dropdown function is called
            console.log("query result: ", results);
        }
        else {
            let noProjectAccess = [];
            createprojectDropdown(noProjectAccess);
        }
    },
    function (error) {
        console.log("query error: ", error);
    }); //End of Query Project Task

Now, my problem is that I have added a third part to this process. Right after the subprojects dropdown is created in onOpen, I want to look for a global variable created from another widget (this works - for brevity's sake, lets assume it works). This global variable is a subproject name. To use it, I first make another query (the 3rd) to a REST Service to get the parent project name that it is associated with. Once that is done I just want to

1) use the parent project name variable (info_proj_name) to select an item from the Projects dropdown- this triggers the on('change') event for the createProjectDropdown function):

 dijit.byId('projectSelect').set("value", info_proj_name);

2) Once the subprojects dropdown has been populated with the subprojects that correspond to the parent project name in #1, I want to select the subproject name (from the subproj_name global variable):

dijit.byId('subprojectSelect').set("value", subproj_name);

This must all happen in order. The project dropdown must first exist in the dom (dijit.byId() must be callable), the subprojects dropdown must then exist in the dom, then the parent project is selected (causing the corresponding subprojects in the dropdown to be populated) and finally, the subproject from the subprojects dropdown must be selected. How can I apply a callback or promise (including Dojo Deferred) to make these events occur in the specified order?

0 Kudos
0 Replies