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.
Solved! Go to Solution.
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.
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.
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.
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
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.
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?
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.
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.
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.
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.