Search code examples
javascriptesriarcgis-js-api

Multiple markers with specific infotemplate content


When I'm looping through a list of addresses, I'm able to plot the markers for all the addresses fine. But when I click on any marker, the infowindow content shows data of only the last marker. How do I solve this?

Javscript

var map ={};
map.markers = [];
map.addresses = [
    {
        'line': '2101 K St',        
        'ref_no': '160621-000005'        
    },
    {
        'line': '2131 K St',        
        'ref_no': '170708-000015'        
    },
    {
        'line': '2321 K St',        
        'ref_no': '170707-000028'
    }
];

.
.
.
map.map_object = new Map("esri_map", {
   basemap: "topo",
   center: [<lat>, <lng>],
   zoom: 12
});

var locator = new Locator("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer");
for(var i = 0; i < map.addresses.length; i++)
{
    var addr = map.addresses[i];
    var params = {
        countryCode: "US",
        maxLocations: 1,
        address: {"SingleLine": addr.line}
    };
    locator.addressToLocations(params, function(candidates){
        locatorDone(candidates, addr);
    });
}

function locatorDone(candidates, addr)
{
    .
    .
    .
    var html = "<h5>"+addr.line+"</h5>";            
    html += "<p>Ref#: "+addr.ref_no+"</p>";
    var infoTemplate = new esri.InfoTemplate(addr.ref_no, html); // <--- Problem lies here
    var graphic = new esri.Graphic(pt, symbol,'',infoTemplate);
    map.map_object.graphics.add(graphic);
    map.markers.push(graphic);
}

P.S: I've solved similar problems (in case of Google Maps API) by using closures. But I'm not sure how to use that in this case.


Solution

  • You can wrap the inside of the for loop in a self invoking function which will provide the closure. Something like this:

    for(var i = 0; i < map.addresses.length; i++) 
        (function (i) {
            var addr = map.addresses[i];
            var params = {
                countryCode: "US",
                maxLocations: 1,
                address: {"SingleLine": addr.line}
            };
            locator.addressToLocations(params, function(candidates){
                locatorDone(candidates, addr);
            });
        })(i)
    

    This will make i local to this code block. As it is now in your code all addr are referencing the last address because the for loop has finished running when you call locatorDone asynchronously. Alternatively you can use let like so: for (let i = 0; ... if you don't need this code to run on Internet Explorer below version 11.