Select to view content in your preferred language

Deferreds and Identify Task

6710
17
05-28-2013 06:28 AM
BrendanDwyer
Frequent Contributor
Asynchronous programming newbie question.  I need to run an identify task on a dynamic map service layer.  After I get the results of the identify, I need to do another operation before the results are sent to the popup.  I'll use that operation to format the infoTemplate.

How do I prevent the popup from displaying until I format it?  It seems that as soon as the result comes back, the dojo will display the popup with the returned records.  I think I need to chain the deferreds or create a deferred list, but I can't grok how it works.


function executeIdentifyTask(evt) {
identifyParams.geometry = evt.mapPoint;
identifyParams.mapExtent = map.extent;
      
var deferred = identifyTask.execute(identifyParams);
       deferred.addCallback(function(response) {    
          // response is an array of identify result objects   
          // Let's return an array of features.
       return dojo.map(response, function(result) {
       var feature = result.feature;
       if(result.layerName === 'Tax Parcels'){
if (blah.length>0) {
  FORMAT CONTENT HERE
          var template = new esri.InfoTemplate("", "${Postal Address} <br/> Owner of record: ${First Owner Name}");
          feature.setInfoTemplate(template);
}
else
{
  FORMAT CONTENT DIFFERENT WAY HERE
          var template = new esri.InfoTemplate("", "${Different Stuff} <br/> Owner of record: ${Blah}");
          feature.setInfoTemplate(template);
}
});
        console.log(feature.attributes.PARCELID);
       }
       else if (result.layerName === 'Building Footprints'){
        var template = new esri.InfoTemplate("", "Parcel ID: ${PARCELID}");
         feature.setInfoTemplate(template);
        }
        return feature;
        });
     });

     
        // InfoWindow expects an array of features from each deferred
        // object that you pass. If the response from the task execution
        // above is not an array of features, then you need to add a callback
        // like the one above to post-process the response and return an
        // array of features.
        map.infoWindow.setFeatures([ deferred ]);
        map.infoWindow.show(evt.mapPoint);
      }
0 Kudos
17 Replies
RobertKirkwood
Frequent Contributor

Kelly,

Hello. I was wondering can the mediaInfos that works with the PopupTemplate work with the infotemplate in the example you helped me with?

like this example:

http://developers.arcgis.com/javascript/sandbox/sandbox.html?sample=query_dojochart

I would like to be able to insert a chart.

Thanks

0 Kudos
KellyHutchins
Esri Notable Contributor

Robert,


Sure you can just replace the InfoTemplate with esri/dijit/PopupTemplate and then you can use mediaquery. Here's an example:

   var taxParcelTemplate = new PopupTemplate({
                    title: "{Postal Address}",
                    description: "Owner of record: {First Owner Name}",
                    mediaInfos:[{
                      type: "barchart",
                      value:{
                        fields:["Current Assessed Value", "Current Summer Taxes Owed", "Current Taxable Value", "Current Winter Taxes Owed"]
                      }
                    }]
                  });
                  feature.setInfoTemplate(taxParcelTemplate);   
RobertKirkwood
Frequent Contributor

Kelly,

If it would have been a snake it would have bit me! Sheesh. Thanks again. I think I get caught up in looking at too many examples instead of just looking at what I already have. Thanks again for your quick response.

If you are interested in what I am doing here is a link to a draft.

http://uwmaps.wygisc.org/WRDS/index.html#

the very last button on the right bottom has some identify tools the last layer called PRISM data 30yr precipitation is the one I used with the charting.

Thanks again!

Robert Kirkwood

Wyoming Geographic Information Science Center

University of Wyoming | Agriculture C, Rm 321

Phone: (307) 766-6281 | Cell: (307) 399-8094

RobertKirkwood
Frequent Contributor

p.s. not the last button but the one above the globe Icon

Robert Kirkwood

Wyoming Geographic Information Science Center

University of Wyoming | Agriculture C, Rm 321

Phone: (307) 766-6281 | Cell: (307) 399-8094

0 Kudos
RobertKirkwood
Frequent Contributor

perfect!

0 Kudos
BrendanDwyer
Frequent Contributor
One option might be to just add the layers you want to query to your application as feature layers in Selection only mode. When you add each feature layer define the info template for that layer.  Note that in this example we don't have to query for attachment info because we've set showAttachments to true when defining the info template for the feature layer that has attachments. Then when you click the map you can use the feature layer's selectFeatures method to select the features of interest and display them in the popup.


Here's a jsfiddle that shows this:

http://jsfiddle.net/Wav9r/


Kelly, thanks for posting.  I've actually implemented your solution as I've tried to work out the problem.  The hangup is that I have to run the identify over many, many layers (hundreds, actually.  Don't ask: Customer wants it this way....).  I'd have to add each feature layer individually and then specify an identify task for each, correct?  

Is there a way to hold up the function from returning the feature until the queryattachmentinfo returns it's data?  I think I need to nest the deferreds, but as I said, I'm not tracking how to do it.  I've tried a couple of different ways and it's not working.
TracySchloss
Honored Contributor
I'm not sure about the nested deferred, but as far as your infoTemplate content, I've been using a function on it, rather than just defining it like you have.  It gave me a lot finer control of it's behavior as opposed to hard coding it and it doesn't  try to format the information until the feature was returned from the identify.  I wanted the contents displayed as a table.  I have a lot of messy attribution, so there are lots of checks in my code to make sure there are values before I add it as a record in the table. 

   parcelInfoTemplate = new esri.InfoTemplate();
   parcelInfoTemplate.setTitle("Parcel Information");
   parcelInfoTemplate.setContent(parcelSetWindowContent);


Here's my identify function that I have set to my map 'onClick'
function doIdentify(event){
    map.infoWindow.hide();
    map.graphics.clear();
        labelPt = event.mapPoint;
        parcelIdentifyParams.geometry = event.mapPoint;
        parcelIdentifyParams.mapExtent = map.extent;
    var deferred = parcelIdentifyTask.execute(parcelIdentifyParams);
        
        deferred.addCallback(function(response){
            var feature = response[0].feature;        
            showInfoWindow(feature,labelPt);          
        });
    }
}
function showInfoWindow (feature, labelPt) {
   feature.setInfoTemplate(parcelInfoTemplate);              
   map.infoWindow.setTitle("Parcel Information");
   map.infoWindow.setContent(feature.getContent());
   map.infoWindow.show(labelPt);              
}

function parcelSetWindowContent(graphic) {
    var nameTest1 = graphic.attributes.NAME1;
    var addressTest = graphic.attributes.SITEADDRES;
    var addressTest2 = graphic.attributes.SITEADDRESS;//very freaky that some seem to have one 's' and other two
    var legalTest1 = graphic.attributes.LEGAL1;
    var legalTest2 = graphic.attributes.LEGAL2;
    var legalTest3 = graphic.attributes.LEGAL3;
    var legalTest4 = graphic.attributes.LEGAL4;
    var fullLegalString;
    var twpRangeSecString;
    var twpTest = graphic.attributes.TOWNSHIP;
    var rngTest = graphic.attributes.RANGE;
    var secTest = graphic.attributes.SECTION;
    if (twpTest != 'undefined' && twpTest != 'Null') {
      twpRangeSecString = "TWP:" + graphic.attributes.TOWNSHIP;
    }
    if (rngTest != 'undefined' && rngTest != 'Null') {
      twpRangeSecString = twpRangeSecString +  "  RNG:" + graphic.attributes.RANGE;
    }
    if (secTest != 'undefined' && secTest != 'Null') {
      twpRangeSecString = twpRangeSecString +  " SEC: " + graphic.attributes.SECTION;
   }
    var acreageTest = graphic.attributes.ACRES;
    var buildingNameTest = graphic.attributes.BUILDING_NAME;
    var bookTest = graphic.attributes.BOOK1;
    var pageTest = graphic.attributes.PAGE1;
    var initString = "";//used to see if there is really any content in the attribute values 
    //There is problem with Null being detected as a 4 character length string instead of just nothing
    //checking to see if the value is longer than 4 characters because of this
   
    initTable = "<table id='infoWindowTable' data-dojo-type='dojox.grid.DataGrid' class='infoTable' ><tr><th></th><th></th></tr>"; 
       if (nameTest1.length > 1) {
        initTable = initTable + "<tr><td><b>Owner:</b></td><td>" + nameTest1+ "</td></tr>";
        initString = nameTest1;
    }
    if (buildingNameTest) {
        if (buildingNameTest.length > 4) {
            initTable = initTable + "<tr><td><b>Building:</b></td><td>" + buildingNameTest+ "</td></tr>";
            initString = initString + buildingNameTest;
        }
    }
    if (addressTest) {
        if (addressTest.length > 4) {
            initTable = initTable + "<tr><td><b>Site Address:</b></td><td>" + addressTest + "</td></tr>";
            initString = initString + addressTest;
        }
    }
        if (addressTest2) {
        if (addressTest2.length > 4) {
            initTable = initTable + "<tr><td><b>Site Address:</b></td><td>" + addressTest2 + "</td></tr>";
             initString = initString + addressTest2;
        }
    }
   initTable = initTable + "</table><br><a id='btnZoom'  onClick='zoomTo();'>Zoom To</a>";
   
  //some counties provided so little information in a field that there wasn't enough information to put 
  //in an infoWindow
  if (initString.length < 3) {
     initTable = "Limited data provided, see side panel.";
  }
  return initTable;
} 


Maybe it will at least give you some ideas of another way to approach your problem.
0 Kudos
BrendanDwyer
Frequent Contributor
Tracy,
Thanks for replying.  I thought about doing a check before the infowindow.show method.  I don't think that would work. 

The problem is that I call the featureLayer.queryAttachmentInfos function inside the deferred.addCallback function.  I call this so that I can get the attachement url and create the feature.template with it.  I want to display the attached photos in the infowindow.

For some reason, the callback function returns the feature before the queryAttachmentInfo returns.  I don't understand this.  It's inside the callback function.  Should everything inside that function operate synchronously?

If I can get the callback function to wait for the queryAttachmentInfo to finish, I'd be all set.  I don't think I can run a test before the onshow method because there might be more than one queryAttachmentInfo method to fire (if more than one features are clicked).
0 Kudos