|
POST
|
Alright, so I finally figured out a way around the dynamic layer and using the polygon feature layer instead. My final issue is setting the definition expression on the polygon layer. I have the expression written out that matches the GUIDs I have in the polygon layer. Unfortunately, after I set the definition expression, it doesn't seem to apply because none of my polygons show up in the map. //Set definition expression of hbMgmtTractFL before adding to map so it displays correctly
//Get OIDs of all current year records in table (defintion expression is set on table)
hbMgmtTableFL.on("load", function () {
var recordIDs = new Query();
recordIDs.where = "1=1";
hbMgmtTableFL.queryIds(query, function (OIDs) {
//Create relationship query
var relatedRecordsQuery = new RelationshipQuery();
relatedRecordsQuery.objectIds = OIDs;
relatedRecordsQuery.outFields = ["MgmtTractID"];
relatedRecordsQuery.relationshipId = 0;
hbMgmtTableFL.queryRelatedFeatures(relatedRecordsQuery, function (fset) {
//Get all MgmtTractIDs for the current year
var MgmtTractIDsArr = [];
for (i = 0; i < OIDs.length; i++) {
var OID = OIDs[i];
var feature = fset[OID].features;
var mgmtTractId = feature[0].attributes.MgmtTractID;
if (!(MgmtTractIDsArr.includes(mgmtTractId))){
MgmtTractIDsArr.push(mgmtTractId);
};
}
//Create the definition expression
var whereClause;
for (i = 0; i < MgmtTractIDsArr.length; i++) {
if (i == 0) {
whereClause = "MgmtTractID = '" + MgmtTractIDsArr[i] + "'";
}
else {
whereClause = whereClause + " || MgmtTractID = '" + MgmtTractIDsArr[i] + "'";
}
}
//Set the polygon feature layer's definition expression based on the GUIDs
console.log(whereClause);
hbMgmtTractFL.setDefinitionExpression(whereClause);
hbMgmtTractFL.refresh();
});
});
}) Instead of on load of the table feature layer, I've tried doing it on the map after all the layers have been drawn, but no dice. I've tried calling the refresh function on the polygon feature layer after I have set the definition expression as well. I can't return the whereClause variable because it's inside a queryRelatedFeatures method so what would be returned is a deferred object, granted I don't think that getting the whereClause out of the functions would make a difference. There are no errors in the console and I've verified the whereClause variable comes through correctly. I'm stumped. The ultimate goal is that when the map initializes the layer will display with the definition expression set without the user having to click any buttons beforehand.
... View more
03-01-2019
07:14 AM
|
0
|
1
|
2383
|
|
POST
|
Nope... QueryTask doesn't work. What's the point of saying you can query a dynamicLayer when you can't query it when it has a join? Either the documentation is wrong or it's a bug. mgmtTractPopupBox.setContent(mgmtPopupContent);
function mgmtPopupContent(feature) {
for (var attrb in feature.attributes) {
if (attrb == "HabitatManagement.DBO.MgmtTracts.OBJECTID") {
var OID = feature.attributes[attrb];
}
}
var mgmtQuery = new Query();
mgmtQuery.objectIds = [OID];
mgmtQuery.outFields = ' ' ;
var mgmtQueryTask = new QueryTask('https://xxx/rest/services/HabitatMonitoring/HabitatData/MapServer/dynamicLayer', {
source: lyrDataSource
});
mgmtQueryTask.execute(mgmtQuery, mgmtQueryResults);
//Format content for popup
function mgmtQueryResults (featureSet) {
console.log(featureSet);
}
} Error I get in the console (It's an arc JS error, not the JS I wrote): TypeError: g.join is not a function at Object.toJson (init.js:1284) at Object.execute (init.js:2223) at Object.c.(anonymous function) [as execute] (https://js.arcgis.com/3.24/init.js:1214:326) at Object.mgmtPopupContent [as content] (HabitatMap.js?v=1:539) at c.getContent (init.js:1244) at Object._updateWindow (init.js:1191) at Object._featureSelected (init.js:1191) at Object.<anonymous> (init.js:63) at Object.c [as onSelectionChange] (init.js:119) at Object.select (init.js:1229) "TypeError: g.join is not a function at Object.toJson (https://js.arcgis.com/3.24/init.js:1284:378) at Object.execute (https://js.arcgis.com/3.24/init.js:2223:30) at Object.c.(anonymous function) [as execute] (https://js.arcgis.com/3.24/init.js:1214:326) at Object.mgmtPopupContent [as content] (http://localhost:14902/Scripts/HabitatMap.js?v=1:539:31) at c.getContent (https://js.arcgis.com/3.24/init.js:1244:248) at Object._updateWindow (https://js.arcgis.com/3.24/init.js:1191:450) at Object._featureSelected (https://js.arcgis.com/3.24/init.js:1191:351) at Object.<anonymous> (https://js.arcgis.com/3.24/init.js:63:337) at Object.c [as onSelectionChange] (https://js.arcgis.com/3.24/init.js:119:193) at Object.select (https://js.arcgis.com/3.24/init.js:1229:278)"
... View more
02-28-2019
06:16 AM
|
0
|
0
|
2383
|
|
POST
|
I do. I have to join the data in order to display it correctly on my map. I have a polygon layer that has a 1-M relationship with records in a table. The records in the table have a "Year" field where the year could be different, so one polygon may have multiple records that have different values in the "Year" field. There is no "Year" field in the polygon layer since some polygons may need to have multiple years associated with it. The problem is I need to be able to let the user set a year in the map and show the polygons that has at least one record with that year, so I need to set a definition expression on the layer based on the year. Since the polygon layer itself does not have the years in it, I need to join the data to get that year to set the definition expression. I may have figured out a way around it though. The QueryTask allows you to use a dynamicLayer, so if I query that, I believe the joined data will come with it and I can display it that way. We'll see if that works... var mgmtQueryTask = new QueryTask('https://xxx/rest/services/HabitatMonitoring/HabitatData/MapServer/dynamicLayer', {
source: lyrDataSource
}
... View more
02-28-2019
06:06 AM
|
1
|
0
|
2383
|
|
POST
|
Well that is a unfortunate.. guess it's back to drawing board on how to set a definition expression on my feature layer that's derived from joined data (which I don't think there is another way). That leaves me with figuring out to query joined data which I also don't think is possible.
... View more
02-27-2019
08:21 AM
|
0
|
3
|
2383
|
|
POST
|
Yes. hbMgmtTractFL is a dynamic layer that displays on the map. queryableMgmtTractFL is a feature layer that is not displayed but is the same layer hbMmgtTractFL. hbMgmtTractFL is not queryable in that there is a join on it which apparently queries don't play nice with, so I've had to create the second feature layer. The user will be clicking features in hbMgmtTractFL, the popup content is generated using queryableMgmtTractFL. Regardless, the hbMgmtTractFL is defined.
... View more
02-27-2019
08:11 AM
|
0
|
5
|
2383
|
|
POST
|
Wouldn't I just run into the same problem though? With a click event, you're still going to have to get the OID, set up the relationship query properties, do the relationship query and generate the popup content and somehow return that popup content to a variable, then define the InfoTemplate with the content set to that variable. That doesn't solve the problem of having nested functions and not being able to return things from the query to the parent function. Anyway, after attempting this it keeps telling me my feature layer is undefined when trying to do this, it breaks my map too: hbMgmtTractFL.on("click", function (feature) {
for (var attrb in feature.attributes) {
if (attrb == "HabitatManagement.DBO.MgmtTracts.OBJECTID") {
var OID = feature.attributes[attrb];
}
}
var relatedQuery = new RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0;
relatedQuery.objectIds = [OID];
//Get data year that the map view is set to and set the definition expression on the table
viewYear = dom.byId("data-year").value;
relatedQuery.definitionExpression = "YearTreated = " + viewYear;
//Run the query and format popup content
var content = queryableMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
var fset = relatedRecords[OID].features;
fset.forEach(function (feature) {
var vegPractice = vegPName(feature.attributes.VegMgmtPractice);
var herbicide = herbName(feature.attributes.Herbicide);
var monthTreated = monthName(feature.attributes.MonthTreated);
var yearTreated = feature.attributes.YearTreated;
var impBy = impName(feature.attributes.ImplementedBy);
var fundBy = fundName(feature.attributes.FundedBy);
var fbc = feature.attributes.FarmBillCode;
if (fundBy == "CRP" || fundBy == "CRP - CREP") {
fbc = crpName(fbc);
}
else if (fundBy == "EQIP" || fundBy == "EQIP - RCPP") {
fbc = eqipName(fbc);
}
else {
fbc = "Not applicable";
}
row = '<tr><td>' + vegPractice + '</td><td>' + herbicide + '</td><td>' + monthTreated + '</td><td>' + yearTreated +
'</td><td>' + impBy + '</td><td>' + fundBy + '</td><td>' + fbc + '</td></tr>';
content = content + row;
});
content = content + '</table>';
console.log(content);
return content;
});
console.log(content);
return content;
});
... View more
02-27-2019
07:56 AM
|
0
|
7
|
3362
|
|
POST
|
Well that would make sense on why I am struggling so much I do show the popup based on a mouse click on the feature. I just have the content formatted at the start of the script and then assign that mgmtTractPopupBox variable to the infotemplate property of a feature layer I define later. //Format the popup content for the habitat management tract feature layer
var mgmtTractPopupBox = new InfoTemplate();
mgmtTractPopupBox.setTitle("${HabitatManagement.DBO.MgmtTracts.StateID} Habitat Management Tract");
mgmtTractPopupBox.setContent(mgmtPopupContent);
//Add the habitat management tract feature layer with the join. This one is used to display on the map.
var hbMgmtTractFL = new FeatureLayer("https://xxx/rest/services/HabitatMonitoring/HabitatData/MapServer/dynamicLayer", {
refreshInterval: 10,
visible: false,
source: lyrDataSource,
outFields: ["*"],
infoTemplate: mgmtTractPopupBox
}); Possibly important to note, I define the popup on a dynamic layer but when I'm running the related features query, I query the same layer only it's a feature layer instead of a dynamic layer (the regular feature layer is also defined, called queryableMgmtTractFL as seen in my original post.
... View more
02-27-2019
07:24 AM
|
0
|
9
|
3362
|
|
POST
|
Yes, I tried that but it doesn't do anything. It returns nothing to the popup window, not even the table headers because you're returning inside the callback function (function(relatedRecords){...}, not the mgmtPopupContent function. I need to return something from the mgmtPopupContent function since that is what the .setcontent() for the InfoTemplate object is set to: mgmtTractPopupBox.setContent(mgmtPopupContent); If you were to do two returns, one inside the anonymous callback function and then one inside the mgmtPopupContent function, it will just return the table headers before anonymous callback function is done.
... View more
02-27-2019
06:45 AM
|
0
|
1
|
3362
|
|
POST
|
If I move the return to line 34 (I think you misspoke in what lines you specified?), nothing gets printed to the popup. That return statement is inside the anonymous callback function and the return to get anything to show up in the popup is inside the mgmtPopupContent function.
... View more
02-27-2019
04:25 AM
|
0
|
3
|
3362
|
|
POST
|
I'm going to ask a pretty much straight JS question because stackexchange can't wrap their minds around the fact that there are javascript platforms that they've never seen before (arcigs javascript api basically).... so, sorry this is going to be a bit out of place but hopefully someone here will understand what I'm saying better. I am trying to populate a InfoTemplate object with content using related table records of a polygon layer. I run the relationship query sucessfully, and then I need to loop through the records and put them in an HTML table format so I can display it in the popup. The problem I'm having is that I'm not sure how to write the code so the asynchronous relationship query finishes before the popup content gets rendered. The anonymous callback function won't finish before the return statement is hit in the function, thus my popup renders the table headers but nothing else. I'm sure I could just shift around the code using a feature layer on click event and do it that way, but I feel that I'm so close to having it done this way that maybe there's a simpler fix. I've fiddled around with JS Promises and moving the anonymous callback function to it's own named function, but just can't seem to figure out how to make those work together. //Call the function that will format the popup content
mgmtTractPopupBox.setContent(mgmtPopupContent);
function mgmtPopupContent(feature) {
//set up the query properties
//....
//Create table header that will go inside popup
var content = '<table id="mgmtPopupTable1"><tr><th>Veg Mgmt Practice</th><th>Herbicide</th><th>Month</th><th>Year</th>\
<th>Implemented By</th><th>Funded By</th><th>Farm Bill Code</th></tr>';
//Run the query - asynchronous process
queryableMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
var fset = relatedRecords[OID].features;
fset.forEach(function (feature) {
var vegPractice = vegPName(feature.attributes.VegMgmtPractice);
var herbicide = herbName(feature.attributes.Herbicide);
var monthTreated = monthName(feature.attributes.MonthTreated);
var yearTreated = feature.attributes.YearTreated;
var impBy = impName(feature.attributes.ImplementedBy);
var fundBy = fundName(feature.attributes.FundedBy);
var fbc = feature.attributes.FarmBillCode;
if (fundBy == "CRP" || fundBy == "CRP - CREP") {
fbc = crpName(fbc);
}
else if (fundBy == "EQIP" || fundBy == "EQIP - RCPP") {
fbc = eqipName(fbc);
}
else {
fbc = "Not applicable";
}
row = '<tr><td>' + vegPractice + '</td><td>' + herbicide + '</td><td>' + monthTreated + '</td><td>' + yearTreated +
'</td><td>' + impBy + '</td><td>' + fundBy + '</td><td>' + fbc + '</td></tr>';
content = content + row;
});
content = content + '</table>';
});
return content; //Returns table header with none of the derived rows
}
... View more
02-26-2019
11:20 AM
|
0
|
18
|
6318
|
|
POST
|
If the relatedRecords object is already a collection of features organized by ObjectIDs, wouldn't you just need to put the OID in question as the key value for the relatedRecords object? If you had multiple object IDs queried (in my case only one will be queried at a time), you'd just need to iterate through. var fset = relatedRecords[OID]
var feature = fset.features[0].attributes I'm a little perplexed by the key you used in the relatedRecords object in the first code line. I would think that would come back as undefined.
... View more
02-25-2019
08:59 AM
|
0
|
1
|
2131
|
|
POST
|
Since the relatedRecords object can contain multiple OIDs and their related records, you have to index using the OID and then get the associated features with that OID. relatedRecords[2470].features[0].attributes
... View more
02-25-2019
08:03 AM
|
0
|
0
|
2131
|
|
POST
|
This is probably a pretty simple javascript syntax question but... I successfully ran a relationship query between a polygon layer and table that has multiple matching records. The problem is that I can't figure out how to access each record's attributes. The object returned from the query contains an array of features, so I figured I would just be able to index and select one single feature from the array, but it's not working out that way. I feel like it has something to do with the OBJECTID used in the relationship query, seen at the very top of the tree ("2470"): What is the syntax for getting at these features/records? queryableMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
console.log(relatedRecords[features[0].attributes]); //Doesn't work
}); Tried this too: relatedRecords.features[0].attributes The error message I get is that "features" is undefined.
... View more
02-25-2019
07:45 AM
|
0
|
4
|
2377
|
|
POST
|
Since feature.attributes returns an object, I just resolved to indexing into it using the full field name as the key. Note, I had to query the related records on the non-joined feature layer, I cannot query related records of a dynamic layer. function mgmtPopupContent(feature) {
for (var attrb in feature.attributes) {
if (attrb == "HabitatManagement.DBO.MgmtTracts.OBJECTID") {
var OID = feature.attributes[attrb];
console.log(OID);
}
}
var relatedQuery = new RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0;
relatedQuery.objectIds = [OID];
noJoinMgmtTractFL.queryRelatedFeatures(relatedQuery, function (relatedRecords) {
console.log(relatedRecords);
});
}
... View more
02-25-2019
06:29 AM
|
0
|
0
|
1295
|
|
POST
|
I have a polygon layer where one polygon matches multiple records in a table. I use JoinDataSource() to join these two items so I can set the definition expression of the polygon layer based on a field in the table. When I go to set the popup content for this polygon feature I need to query the records in the table that are related with the polygon layer. To use a relationship query, you need the objectId of the polygon, but I can't get that using feature.attributes.fieldName because the field name itself has a bunch of periods in it due to the database and tables names being prefixed on it. Using something like this won't work because javascript misinterprets the periods: feature.attributes.HabitatManagement.DBO.MgmtTracts.OBJECTID How do I get around this? Here is the relationship query code: function mgmtPopupContent(feature) {
var OID = feature.attributes.HabitatManagement.DBO.MgmtTracts.OBJECTID;
var relatedQuery = new RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0;
relatedQuery.objectIds = OID;
hbMgmtTractFL.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
//set popup content
}
}
... View more
02-25-2019
06:09 AM
|
0
|
1
|
1354
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 06-18-2020 10:31 AM | |
| 2 | 09-16-2025 02:17 PM | |
| 3 | 09-12-2025 09:26 AM | |
| 1 | 08-16-2023 05:11 PM | |
| 1 | 02-27-2024 06:48 AM |
| Online Status |
Offline
|
| Date Last Visited |
09-16-2025
02:16 PM
|