Select to view content in your preferred language

Want to create a module for this QueryTask functionality

4780
26
Jump to solution
08-10-2015 02:29 PM
TracySchloss
Frequent Contributor

I have two external tables that contain an ID and a description.  They are the basis for a set of menus, and since they are very similar in their schema, I'm attempting to create one tool  for creating an array of code and description pairs.  In addition, I'm using this as a learning tool for defining modules and it's not going so well. These these will eventually be input for menus, as well as look

These are two different tables and the field names are not  identical, so I need to account for that as well.

In my Map module, myMap.js, I have defined this variable, which is a table I have loaded as a featureLayer, along with several other layers.

        var specUrl = specialtyTable.url;

added a listener for the map load event:

myPopulateCodeList.populateCode('spec',specUrl);

The function populateCode is getting called, but I need to keep the codeList array as a variable, because I'll use it again in more than one place.

myPopulateCodeList.js

 define([
  "dojo/on", 
  "esri/tasks/QueryTask", 
  "esri/tasks/query"
  ], function(
  on,QueryTask, Query){
  var codeList = [];
      return {
        populateCode: function(codeType, url){
          switch (codeType) {
            case "spec":
              codeAtt = 'ID_SPECIALTY_PK';
              specAtt = 'TX_SPECIALTY_DESC';
              break;
            default:
              codeAtt = 'ID_PROV_TYPE_PK';
              specAtt = 'TX_PROV_DESC';
              break;
          }
          var queryTask = new QueryTask(url);
          var query = new Query();
          query.outFields = ["*"];
          query.where = "1=1";
          query.returnGeometry = false;
          on(queryTask, 'complete', this.codeResultsHandler);
          on(queryTask, 'error', this.errorHandler);
          queryTask.execute(query);
        },
        
        //builds codeList object containing codes and descriptions 
        codeResultsHandler: function(results){
          var numResults = results.featureSet.features.length;         
            for (var j = 0; j < numResults; j++) {
              var code = results.featureSet.features.attributes[codeAtt];
              var desc = results.featureSet.features.attributes[specAtt];
              codeList.push({
                code: code,
                desc: desc
              });
            }
            console.log('end of codeList array build');
            return codeList;
          },
        
        errorHandler: function(err){
          console.log("error in myPopulateCodeList, error: " + err.details);
        }
        
      }
    return codeList;
     
    });

I can see that codeList is getting populated with values from the results handler of the queryTask, but I can't figure out how to pass this result back to the calling function.  This doesn't work:

var specCodeList = myPopulateCodeList.populateCode('spec',specUrl);

When I had it all in one big file, this was working, but I'm trying to learn how to break my work up into smaller bits.

0 Kudos
26 Replies
RobertWinterbottom
Occasional Contributor

Ok, sounds like you may want to step through the callback to the query task as that may not be populating your codeList array, if it is, then you will want to figure out the best way for you to return it or return a signal that the query task is complete and the data is available.

0 Kudos
TracySchloss
Frequent Contributor

I added an app variable and passing it to myMap.js. 

This lets me do this with my codeLists:

myPopulateCodeList.populateCode('spec', specUrl).then(function (codeList) { 

          app.specCodeList = codeList;

            console.log(codeList); 

          }, function (err) { 

            console.error(err); 

          }); 

         myPopulateCodeList.populateCode('prov', provUrl).then(function (codeList) { 

          app.provCodeList = codeList;

            console.log(codeList); 

          }, function (err) { 

            console.error(err); 

          }); 

        });

I have two objects in app, but when I look at them more closely, they contain the exact same thing - the values from the first table I processed. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tracy,

   If you are going to reuse the myPopulateCodeList then you will have to clear the codeList array each time you do populateCode function.

populateCode: function(codeType, url){
    this.codeList = [];
    var codeAtt, specAtt;
    ....

Or you create a new myPopulateCodeList each time.

RobertWinterbottom
Occasional Contributor

Yes seems like your getting a reference to myPopulateCodeList.codeList.  If your going to store those codeLists in the global scope then I would recommend modifying the module a little so codeList is not a property of myPopulateCodeList to prevent issues like this.  Here is an example of the original sample I posted with some changes to make codeList not a property of myPopulateCodeList module.

define([    
  "dojo/on",    
  "esri/tasks/QueryTask",    
  "esri/tasks/query",    
  "dojo/_base/lang",  
  "dojo/Deferred"    
  ], function(    
  on, QueryTask, Query, lang, Deferred){    
  var mo = {    
    //codeList: [],   We don't want this as a property here, it should be a local variable in function below  
    populateCode: function(codeType, url){    
      var codeAtt, specAtt, codeList = [];  // Added local codeList here
      var deferred = new Deferred();    
      switch (codeType) {    
        case "spec":    
          codeAtt = "ID_SPECIALTY_PK";    
          specAtt = "TX_SPECIALTY_DESC";    
          break;    
        default:    
          codeAtt = "ID_PROV_TYPE_PK";    
          specAtt = "TX_PROV_DESC";    
          break;    
      }    
      var queryTask = new QueryTask(url);    
      var query = new Query();    
      query.outFields = ["*"];    
      query.where = "1=1";    
      query.returnGeometry = false;    
      queryTask.execute(query, lang.hitch(this,function(results){    
        var numResults = results.featureSet.features.length;    
        for (var j = 0; j < numResults; j++) {    
          var code = results.featureSet.features.attributes[codeAtt];    
          var desc = results.featureSet.features.attributes[specAtt]; 
          // push to the local codeList and not this.codeList   
          codeList.push({    
            code: code,    
            desc: desc    
          });    
        }    
        console.log("end of codeList array build");   
        deferred.resolve(codeList);  
      }), function(err){    
        console.log("error in myPopulateCodeList, error: " + err.details);  
        deferred.reject(err);    
      });   
      return deferred;   
    }    
  };    
  return mo;    
});  

What was happening was that when you called the populateCode function, it was updating the myPopulateCodeList.codeList property. So when you call populateCode function it just updates the same property no matter what you pass into it.  Doing it this way returns a new codeList each time and then you can append it to your global codeLists

0 Kudos
TracySchloss
Frequent Contributor

That didn't do it.  And I'm mistaken, they aren't both populated with the values of the first pass, they're both populated with the values from the 2nd time I called it. 

0 Kudos
RobertWinterbottom
Occasional Contributor

Did you try making codeList a local variable inside the populateCode function?  Try getting rid of this.codeList altogether and using var codeList = []; inside the populateCode function. If so, can you post your populateCode code for us to see?

0 Kudos
TracySchloss
Frequent Contributor

It's the code you posted that had codeList as a local variable.  There's enough posts here they are a little out of sequence.  I was replying to comments at the same time other people were posting.

I do have two different codeLists stored under "app".  I'm not sure these are going to be available in all the places I need them, though.  I need to work a little further and see.

0 Kudos
RobertWinterbottom
Occasional Contributor

If app is global then it will be available everywhere without the need for you to pass it around.  global variables attach themselves to the window object.  I think you should be close, I don't see any reason why the code posted would return the same object from two different queries if it is creating a new array each time you query.

TracySchloss
Frequent Contributor

It doesn't anymore.  My comment about them being the same is a reply to Robert's post.   I can never decide whether I should Reply to an individual post or 'Reply to original post'.  It completely changes the order the threads are listed. Your version works.

This is  an exercise for me in how to think in terms of modules.  I have a working project, just all in one big file.  I'm reviewing one section of code at a time, trying to determine what logically should go into its own module. 

0 Kudos
RobertWinterbottom
Occasional Contributor

Ah ok got it, Yea the forum setup is a bit wonky sometimes.  And the fact that there are two Roberts replying probably doesn't make it any less confusing haha.  Seems like you have a good start though so good luck.

0 Kudos