Relationship Query ??? Legacy to AMD

1376
10
10-17-2013 04:47 PM
NumaGremling
New Contributor
Hi everyone,

I am trying to use a relationship query in my application. About 5 months ago I had never used HTML, CSS or JavaScript, so I am very dependent on the provided samples. The only provided AMD sample has a lot of additional stuff and gets complicated quickly for me, and therefore I have tackled a legacy sample ??? I even get it to work. Translating the script into AMD is my next step, but it turns out to be harder than expected.

OK, so I have reduced my 600-line code to about 200 lines. Once I get that working I will add the previous stuff again. I am attaching two scripts, the first one (QueryRelatedWORKING) is in legacy mode and it is able to correctly query my table (click on a parcel ??? display a table). If I had a one-to-one translation of that script into AMD I would be more than happy. The second one (QueryRelatedTRANSLATE) is my attempt to translate into AMD. Viewing both codes next to each other is perhaps the easiest way to detect problems.

I added //OK to lines in the original script that I am pretty sure I translated correctly. If I was unsure, ran into issues, or have questions I left a comment saying so.

My biggest issue (and maybe solution to a lot of it) is that I am not sure where to import things in the beginning statements before you start coding. What I mean is :

require(
["esri/map",
"esri/a",
"esri/b",
"esri/c",
],
function(Map, a, b, c){
var map = new Map
var ??? = new a
var ??? = new b

etc. etc.

The way it works, I read, is that you have to mention things in the correct order. Which is fine in a simple application but once it gets complicated that becomes impossible for a beginner, especially when dojo is thrown into that (which I am not familiar with). For example, what happens if I use things twice? And where do I put the dojo stuff? Can I mix dojo, dijit, and dojox? Looking at samples I???d say I need to put the esri stuff first and then the dojo stuff, but ordering within dojo becomes complex quite fast.

Again, I am a beginner so please point out even the most obvious mistakes. Any advice and correction is greatly appreciated 🙂

PS: I???d be happy to post both scripts in here as well, but if I remember correctly from what I read a while ago one should not post long codes.
0 Kudos
10 Replies
JohnGravois
Frequent Contributor
the AMD module for Query is actually "esri/tasks/query", not "esri/tasks/Query" as per doc here.

a lack of calling dojo.ready() in your AMD version is definitely not a problem, check out this blog for more info on translating between the two patterns..

when using on event style instead of dojo.connect, event names like "onSelectionComplete" become "selection-complete", also, when naming the function which will be called when the event is fired, don't use the '()'.  check out this article for more info.

ie:
mainMap.on("onClick", findParcel());
//should be
mainMap.on("click", findParcel);


you did just fine translating dojo.map() to array.map() 🙂

those were all my changes and the grid was working, hard to be positive its totally done though, because i couldn't hit your own services.
0 Kudos
NumaGremling
New Contributor
Thank you so much for your incredible help. You clarified a lot for me and I have a much better idea how to tackle problems like these now. I have been able to solve a few things that I have been struggling with for weeks based upon your answers! I am still not able to see my relationship table when clicking on the parcel, but anything else works fine now. I hope that I can figure that out soon.

Just to make sure the code below is the correct approach. The way I understand it is that everything in require and in the function need to be in the exact same order. Any ordering after that does not matter (unless it would interfere with the code�??s logic, of course)? For example, I could define and use a variable for Extent before defining a variable for Query, right?

[HTML]
<script>
      require(
   ["esri/map",
   "esri/layers/ImageParameters",
   "esri/layers/ArcGISDynamicMapServiceLayer",
   "esri/symbols/SimpleMarkerSymbol",
   "esri/layers/FeatureLayer",
   "esri/InfoTemplate",
   "esri/tasks/RelationshipQuery",
   "esri/tasks/query",
   "esri/geometry/Extent",
      "esri/toolbars/draw",

   "dijit/layout/BorderContainer",
   "dijit/layout/ContentPane",
   "dojox/grid/DataGrid",
   "dojo/data/ItemFileReadStore",
  
      "dojo/on",
   "dojo/_base/Color",
   "dojo/_base/array",
   "dojo/dom",
      
   "dojo/domReady!"
   ],
  

   function(
   Map,
   ImageParameters,
   ArcGISDynamicMapServiceLayer,
   SimpleMarkerSymbol,
   FeatureLayer,
   InfoTemplate,
   RelationshipQuery,
   Query,
   Extent,
   Draw,
  
   BorderContainer,
   ContentPane,
   DataGrid,
   ItemFileReadStore,
  
   on,
   Color,
   array,
   dom) {  });
</script>
[/HTML]
0 Kudos
JohnGravois
Frequent Contributor
you're correct that the order of the modules loaded and argument aliases that refer to those modules need to match exactly.  since the callback isn't actually triggered until each and every module has been retrieved successfully, this means that you can declare variables and instantiate objects using the argument aliases afterward in any order you want.

glad to hear the information i posted previously was helpful! 🙂
0 Kudos
NumaGremling
New Contributor
Awesome! Knowing that for sure makes looking at sample scripts much easier for me. Thank you so much again for all your great help. More questions soon!
0 Kudos
NumaGremling
New Contributor
I got some help this morning from someone who knows how to debug correctly.
We found out that lines like these in Legacy:

relatedTopsQuery.objectIds = [features[0].attributes.OBJECTID];

become:
relatedTopsQuery.objectIds = [features.features[0].attributes.OBJECTID];

in AMD.

Now it is definitely calling my relationship correctly. However, I am still struggling with displaying the results in the table. I would assume that the issues are linked to the grid that is defined in line 142 (I have attached an updated script).

Also, I translated dojox.grid.DataGrid to dojox/grid/DataGrid but reading up the documentation about how grids work it tells me that:

This document covers the dojox/grid/DataGrid. Beginning with Dojo 1.7, you should use dgrid or gridx, next-generation grid components that take full advantage of modern browsers and object stores.
See here.

Is that perhaps the root of the problem? And how would I change that? I have been searching for a while but Dojo is not the easiest to get into as a beginner.

EDIT:
I also just realized that sometimes dojo items are mentioned in the require statement and in the function, and sometimes not. What is the difference? For example, after looking at different samples (including the Dojo website) I have commented out BorderContainer, ContentPane, and DataGrid, but looking at my JavaScript API Training now I realize that they are mentioned in both places.
0 Kudos
JohnGravois
Frequent Contributor
even though Dojo doc recommends you upgrade, for the time being, it is still safe to use "dojox/grid/DataGrid".

with regard to your second question, there's no harm in writing out a corresponding argument alias for every individual module, but its only really necessary if you plan on leveraging it at least once from within your JavaScript code.

since BorderContainer, Content Pane and other similar modules are typically only referenced from HTML (using their new slashes instead of dots), we can safely omit their argument aliases in our require callback as long as we make sure to load them after all modules that actually need one.

to keep things straight i like to include a space betweeen the modules that have an argument alias and those that omit one in the list of loaded modules , which you are already doing in your own TRANSLATE sample.
require([
    "esri.Map",
    "esri/layers/ArcGISDynamicMapServiceLayer",

    "dijit/layout/BorderContainer"  //no argument alias required
],...
0 Kudos
NumaGremling
New Contributor
Thank you so much again, that makes a lot of sense, and I'm slowly understanding how Dojo works. I added a tab container programmatically last night and I see now why it mattered that I mentioned the elements initially.

My friend was helping me debug my script and we found out that it stops running right after this statement:
          //Create data store and bind to grid.
    var grid;
          store = new ItemFileReadStore({ data:data });
          grid.setStore(store);
          grid.setQuery({ OBJECTID: '*' });
        });
      } 


The entire script is still the same as it was in the last attachment I uploaded. Do you see anything wrong around there? The syntax is still confusing to me so it is hard to troubleshoot.
0 Kudos
JohnGravois
Frequent Contributor
which exact statement?  there are four there :).

i can't really debug from here without access to your services, but when i load your TRANSLATE sample and look at the script tag in the browser developer tools i'm not seeing the 'ItemFileReadStore' argument alias thats in your actual code.  (see attached screenshot).

i have a hunch this is because of the three commented out argument aliases directly above it.

if that doesn't fix the problem you'll have to step through the working code, interrogating variables along the way and checking the console, to find out exactly where its blowing up.
0 Kudos
JohnGravois
Frequent Contributor
please disregard that screenshot and the associated suggestion.  i was pointing at an outdated version of your app from several days ago.
0 Kudos