Select to view content in your preferred language

Can I put related data in a popup?

3132
10
Jump to solution
06-21-2016 02:49 PM
TracySchloss
Honored Contributor

I can find very few postings about relationshipQuery and the ones dealing with popups seem very old.  Is there anyone attempting to do this? 

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  Here is your app working.

Issue were in the index.html:

var popup = new Popup({markerSymbol: highlightSymbol}, domConstruct.create("div"));

you were specifying a highlightSymbol but not defining the proper object for the constructor.

And the myIdentify.js you needed to use deferreds for your functions and then change how and when the popup displayed the results as there is this note for the popup dijit:

Note: the Popup class doesn't support the deferred object option for setting content.

And some wrong field names/attributes

View solution in original post

10 Replies
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  What are you attempting to do? This workflow in this sample works great for me.

Popup with related fields | ArcGIS API for JavaScript

As far as adding related data to a popup. I am not doing anything with relationshipQuery though.

0 Kudos
TracySchloss
Honored Contributor

I have a point layer of schools, and a related table of radon tests.  I only have one year's worth of test data so far, but the idea is that you could view all tests for a school over the years.

What the user requested for the popup is the name of the school and the last year tested.  This sounds simple to them, but with the test results all in the related table, not only would you have to reach into the relationship, you'd also have to sort through the results of the year field to find the most recent.  Then you'd have to pass that to your popup content.

They want to see all the results in a table, which could be in the footer.  I'm thinking this could be a featureTable filtered on the results of relationshipQuery?  Or maybe just filtered, period.  I'll know the school ID and I can limit the table to just those results, I think.

At the moment, the related table isn't even set up with a relationship, since they didn't give me a unique ID to tie it together. I sent it back to see if they could do a little more data massage to add it.   Instead, I'm attempting to handle this through an identify. I'm still thinking through this.  This is called from a map click event:

 define ([ 
    "dojo/on",
 "dojo/_base/array", 
    "dojo/_base/lang", 
    "dojo/Deferred",
    "esri/tasks/IdentifyTask",
    "esri/tasks/IdentifyParameters",
 "esri/tasks/query",
 "esri/tasks/QueryTask",
    "esri/geometry/Point",
    "esri/geometry/Extent"
    ], function ( 
      on, arrayUtils,lang,Deferred,IdentifyTask,IdentifyParameters, Query,QueryTask, Point,Extent
    ) {  
    return {
  runIdentify: function(map, url, point){
   map.setInfoWindowOnClick(false);
   var identifyTask = new IdentifyTask(url);
   var idParams = new IdentifyParameters();
   var def = new Deferred();
   idParams.geometry = point;
   idParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
   idParams.layerIds = [0];
   var pxWidth = map.extent.getWidth() / map.width;
   var padding = 100 * pxWidth;
   var qGeom = new Extent({
    "xmin": point.x - padding,
    "ymin": point.y - padding,
    "xmax": point.x + padding,
    "ymax": point.y + padding,
    "spatialReference": app.spatialReference
   });
   idParams.geometry = point;
   idParams.mapExtent = qGeom;
   idParams.tolerance = 5;
   idParams.returnGeometry = true;
   app.cityName = "";
   
   identifyTask.execute(idParams).then(lang.hitch(this, function(results){
    var fs = [];
    if (results.length > 0) {
     arrayUtils.forEach (results, function( result) {
      var feature = result.feature;
      var formatString = "";
      var ctyDist = feature.attributes.CtyDist;
      var locTest = feature.attributes.Loc_Code;
      var nm = feature.attributes.Facility
      
      formatString = "<b>" + feature.attributes.Facility + "</b><br/>" +
      feature.attributes.Address +
      "<br/>" +
      feature.attributes.City +
      ", MO  " +
      feature.attributes.ZIP
      
      var addedString = new Deferred(); 
      
      addedString = findSchRelatedRecords(nm, ctyDist);
      
      formatString += "<br/>" + addedString;
      return feature;
     });
     app.map.infoWindow.setFeatures([def]);
     app.map.infoWindow.show(point);
     
    }
    return def;
    
   }));
        function findSchRelatedRecords(nm, id){
    var relString = " ";
                var schQuery = new Query;
                var queryTask = new QueryTask(app.testTable.url);
                var whereClause = "Facility = '" + nm + "' AND Dist_Code = '" + id + "'";
                schQuery.where = whereClause;
                schQuery.returnGeometry = false;
                schQuery.outFields = ['*'];
                
                queryTask.execute(schQuery, lang.hitch(this, function(results){
                    
                    var len = results.features.length;
                    if (len === 0) {
                        relString += "No test results found";
                    }
                    else {
                        arrayUtils.forEach(results, function(r){
                            relString += "Start Year: " + r.attributes.ScholYearStart;
                        });
                    }
                    
                }));
                return relString;
            }
  }
 }
});
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  I would not worry about setting up a true relationship. You can definitely filter the FeatureTable (I have provided a post or two on this). I would look into using the StatisticDefintion to get the MAX date for the school in the QueryTask. I think the Identify route will work fine just add the StatisticDefintion to your QueryTask to get the latest Radon test date.

0 Kudos
FC_Basson
MVP Regular Contributor

Robert, would it be possible to use the layer's "orderByFields" property to sort the relationship results by date in descending order and then just use the first result in the list?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

FC,

  I would look into using the StatisticDefintion to get the MAX date.

StatisticDefinition | API Reference | ArcGIS API for JavaScript

TracySchloss
Honored Contributor

At this stage I'd be happy if I could get any values out of my related table, whether through a 2nd query or a true relationshipquery.  It seems like I ought to be able to come back and add code to find the max year without having to scrap what I've done so far. 

My identify is setting the content of the infotemplate up to a point, but my sequence is off for getting and adding the extra information from the table.  I'm only getting the values from the featurelayer, not the other table. 

Here's what I have so far.  I can attempt to put it in jsbin or something if that makes it easier for someone. 

Sample Radon Testing - School

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  Here is your app working.

Issue were in the index.html:

var popup = new Popup({markerSymbol: highlightSymbol}, domConstruct.create("div"));

you were specifying a highlightSymbol but not defining the proper object for the constructor.

And the myIdentify.js you needed to use deferreds for your functions and then change how and when the popup displayed the results as there is this note for the popup dijit:

Note: the Popup class doesn't support the deferred object option for setting content.

And some wrong field names/attributes

TracySchloss
Honored Contributor

I had discovered the popup problem after lunch.  That was me deleting too many lines of code trying to get minimal lines of code to post as my sample.   The other was what I knew I needed to get to, without knowing how to get there.  Awesome!

0 Kudos
TracySchloss
Honored Contributor

Here's the identify code, 'myIdentify.js,  with the statisticdefinitions included.  In my case,  this is school year data, which spans calendar year.  The user wanted the 'startschoolyear' and 'endschoolyear' as separate fields. It didn't make sense to include any of the other statistics available, but I can see how they could easily be included.

define([
    "dojo/on",
    "dojo/_base/array",
    "dojo/_base/lang",
    "dojo/Deferred",
    "esri/InfoTemplate",
    "esri/tasks/IdentifyTask",
    "esri/tasks/IdentifyParameters",
    "esri/tasks/query",
    "esri/tasks/QueryTask",
    "esri/tasks/StatisticDefinition",
    "esri/geometry/Point",
    "esri/geometry/Extent"
], function(
    on, arrayUtils, lang, Deferred, InfoTemplate, IdentifyTask, IdentifyParameters, Query, QueryTask, 
 StatisticDefinition, Point, Extent
) {
    return {
        runIdentify2: function(point, url) {
            app.map.setInfoWindowOnClick(false);
            var identifyTask = new IdentifyTask(url);
            var identifyParams = new IdentifyParameters();
            var def = new Deferred();
            app.pt = point;
            identifyParams.geometry = point;
            identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
            identifyParams.layerIds = [0];
            var pxWidth = app.map.extent.getWidth() / app.map.width;
            var padding = 100 * pxWidth;
            var qGeom = new Extent({
                "xmin": point.x - padding,
                "ymin": point.y - padding,
                "xmax": point.x + padding,
                "ymax": point.y + padding,
                "spatialReference": app.spatialReference
            });
            identifyParams.geometry = point;
            identifyParams.mapExtent = qGeom;
            identifyParams.tolerance = 5;
            identifyParams.returnGeometry = true;
            identifyTask.execute(identifyParams, function(response){
              var newFeats = [];
              arrayUtils.map(response, lang.hitch(this, function(result, indx) {
                var feature = result.feature;
                var infoTemplate = new InfoTemplate("Test Results");
                createInfoContent(feature).then(lang.hitch(this, function(str){
                  console.info(str);
                  infoTemplate.setContent(str);
                  feature.setInfoTemplate(infoTemplate);
                  newFeats.push(feature);
                  console.info(newFeats);
                  console.info(response.length);
                  if(indx === response.length - 1){
                    console.info(newFeats);
                    app.map.infoWindow.setFeatures(newFeats);
                    app.map.infoWindow.show(point);
                  }
                }));
              }));
            });
            function createInfoContent(graphic) {
                var maindef = new Deferred();
                var formatString = "";
                var ctyDist = graphic.attributes.CtyDist;
                var locTest = graphic.attributes.Loc_Code;
                var id = graphic.attributes.SchID;
                formatString = 
                 "<b>" + graphic.attributes.Facility + "</b><br/>" 
                + graphic.attributes.Address 
                +  "<br/>" + graphic.attributes.City +  ", MO  " + graphic.attributes.ZIP;
     
                  findSchRelatedRecords(id).then(lang.hitch(this, function(str){
                  formatString += str;
                  maindef.resolve(formatString);
                }));
                return maindef;
            }
            function findSchRelatedRecords(id) {
                var maindef = new Deferred();
                var relString = "";   
       
  var maxStartStatDef = new StatisticDefinition();
   maxStartStatDef.statisticType = "max";
  maxStartStatDef.onStatisticField = "SchoolYearStart";
   maxStartStatDef.outStatisticFieldName = "latestSchoolYearStart";
    
  var maxEndStatDef = new StatisticDefinition();
      maxEndStatDef.statisticType = "max";
  maxEndStatDef.onStatisticField = "SchoolYearEnd";
   maxEndStatDef.outStatisticFieldName = "latestSchoolYearEnd";
    
    
                var schQuery = new Query();
                var queryTask = new QueryTask(app.testTable.url);
                var whereClause = "SchId = '" + id + "'";
                schQuery.where = whereClause;
                schQuery.returnGeometry = false;
                schQuery.outFields = ['*'];
    schQuery.outStatistics = [ maxStartStatDef,maxEndStatDef];
    
                queryTask.execute(schQuery, lang.hitch(this, function(results) {
                    var len = results.features.length;
                    if (len === 0) {
                        relString += "<br/>No test results found";
                    } else {
   var latestYearStart = results.features[0].attributes.latestSchoolYearStart;
   var latestYearEnd =  results.features[0].attributes.latestSchoolYearEnd;
   relString += "<br/>Last Year Tested: " + latestYearStart + " / " + latestYearEnd;
                    }
                    maindef.resolve(relString);
                }));
                return maindef;
            }
        }
    };
});
0 Kudos