ArcGIS Javascript API v3.21 : I can't display the content of InfoTemplate using deferred object when I am clicking on a Graphic

3189
7
08-23-2017 06:51 AM
KostasPapakonstantinou
New Contributor

Hello,

I use "arcgis for javascript 3.21" and I have created a map with some graphics (points). The problem is that I can't display the content of infowindow because I get an error message.

...

var getPopupTemplate = function(target) {
    var towerId = target.attributes.id;

    var requestObj = {
   url: "http://...",
   content: {
      ...
   },
   handleAs: "json"
};
var markerInfoResponseSuccess = function(response) {
console.log(response);
var markerInfo = response.markerInfo;
var html = "<a href=" + markerInfo.url + ">" + markerInfo.title + "</a>";

return html;
};

var markerInfoResponseError = function(error){
console.log("There was an error on 'get marker info' request: ", error);
};

return esriRequest(requestObj).then(
markerInfoResponseSuccess,
markerInfoResponseError
);
};
var pt = new InfoTemplate({
    content: getPopupTemplate
});
var markerSymbol = new PictureMarkerSymbol({
    "url"   : "http://...",
    "width" : 10,
    "height": 10
});
var point = new Point({
    longitude: ...,
    latitude: ...
});

var pointAtt = {
    title: "myTitile",
    id: 100
};

// Create a graphic and add the point geometry and pin(symbol) to it
var pointGraphic = new Graphic( point, markerSymbol, pointAtt, pt);

....

When I click on the point I can see the response on console but I get the following error, and the content on the infowindow is empty. If I use :

var pt = new InfoTemplate({
    content: "my text"
});

then everything is OK. What's the problem?

TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at Object.b.place (init.js:208)
    at Object.place (init.js:1184)
    at Object.setContent (init.js:1149)
    at Object._updateWindow (init.js:1157)
    at Object._featureSelected (init.js:1157)
    at Object.<anonymous> (init.js:63)
    at Object.c [as onSelectionChange] (init.js:119)
    at Object.select (init.js:1191)
    at Object._updateFeatures (init.js:1197)
    at init.js:62 "TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at Object.b.place (https://js.arcgis.com/3.21/init.js:208:402)
    at Object.place (https://js.arcgis.com/3.21/init.js:1184:263)
    at Object.setContent (https://js.arcgis.com/3.21/init.js:1149:278)
    at Object._updateWindow (https://js.arcgis.com/3.21/init.js:1157:500)
    at Object._featureSelected (https://js.arcgis.com/3.21/init.js:1157:254)
    at Object.<anonymous> (https://js.arcgis.com/3.21/init.js:63:277)
    at Object.c [as onSelectionChange] (https://js.arcgis.com/3.21/init.js:119:193)
    at Object.select (https://js.arcgis.com/3.21/init.js:1191:258)
    at Object._updateFeatures (https://js.arcgis.com/3.21/init.js:1197:246)
    at https://js.arcgis.com/3.21/init.js:62:468"

thank you,

Kostas

0 Kudos
7 Replies
ThomasSolow
Occasional Contributor III

At this point in your code:

var pt = new InfoTemplate({
    content: getPopupTemplate
});

You're setting the content equal to the result of getPopupTemplate, which is a promise (or a deferred object).  You need to reformulate things roughly like this:

getPopupTemplate(target).then(function(html){
  var pt = new InfoTemplate({
    content: html
  });
});‍‍‍‍‍
0 Kudos
ThomasSolow
Occasional Contributor III

To give a little more details, it does seem that you can set an InfoTemplate's content to a function, but it's not clear to me that that function can return a deferred object.  This example doesn't work:

function giveString(){
  return new Promise(fulfill => {
    setTimeout(()=>fulfill('content'),500);
  });
}

// throws error
let template = new InfoTemplate({
  content: giveString
});

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
KostasPapakonstantinou
New Contributor

There is an example in Format info window content | Guide | ArcGIS API for JavaScript 3.21 

under "Deferred Object" :

("In some cases, the content you want to display is not immediately available. It may be content that you need to download from a server using esri/request, which returns an instance of dojo/Deferred...")


function getTextContent(graphic) {
  var geometry = webMercatorUtils.webMercatorToGeographic(graphic.geometry);
  soeParams.InputPolyline = JSON.stringify(geometry.toJson());
  var def =  esriRequest({
    url: soeURL,
    content: soeParams,
    callbackParamName: "callback",
    load: function(fset) {
      return "<img src='" + fset.profileImageUrl + "'/>";
    }
  });
  return def;
}

So, I wrote my code like this :

function getPopupTemplate2(target) {
      var towerId = target.attributes.id;
      var requestObj = {
          url: ...,
          content: {
            ...
          },
          callbackParamName: "callback",
          handleAs: "json",
          load: function(response) {
               console.log(response);
               var markerInfo = response.markerInfo;
               var html = "<a href=" + markerInfo.url + ">" + markerInfo.title + "</a>";
       
               return html;
          }
      };
      var def =  esriRequest(requestObj);

      return def;
}

...

var pt = new InfoTemplate({
    content: getPopupTemplate2
});

...‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

var pointGraphic = new Graphic( point, markerSymbol, pointAtt, pt);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

but again I get the same error

Any thoughts?

P.S : The example ArcGIS API for JavaScript Sandbox  doesn't seem to work.

0 Kudos
KenBuja
MVP Esteemed Contributor

The sandbox version of the sample may not be working since it involves a proxy. The description in the sample does need updating, since it refers to "dojo.Deferred", "deferred.callback", and "deferred.errback", none of which actually appear in the script.

However, the live version does work properly: Info window with deferred object 

KostasPapakonstantinou
New Contributor

I use the following code as it is descripted here Info window with deferred object | ArcGIS API for JavaScript 3.21 , too. Again the same error

function getPopupTemplate3(target) {
     var deferred = new dojo.Deferred();
     var towerId = target.attributes.id;

     var requestObj = {
          url: ...,
          content: {...},
          callbackParamName: "callback",
          handleAs: "json",
          load: function(response) {
               var markerInfo = response.markerInfo;
               deferred.callback("<a href=" + markerInfo.url + ">" + markerInfo.title + "</a>");
          },
          error: function(error) {
               deferred.errback("Error occurred...");
          }
     };
     esri.request(requestObj);

     return deferred;
}
0 Kudos
ThomasSolow
Occasional Contributor III

After playing with it for a bit I got this sample to work: JS Bin - Collaborative JavaScript Debugging 

That fetches some html from the feature service and parses that into a dom node and uses that node as the content for the infoTemplate.

KostasPapakonstantinou
New Contributor


What I'm trying to do is to add some points on the map. I get these points with ajax request from a server where I have wrote the code and I use the default GraphicsLayer (and not a featureLayer) to add these points on the map


var pointGraphic = new Graphic( point, markerSymbol, pointAtt, pt);

self.map.graphics.add(pointGraphic);

I get the content of infowindow from a server where I have wrote the code (and not from a third party) with ajax request, again

I used your idea like that :

var pt = new InfoTemplate({
    content: getPopupTemplate2
});

function getPopupTemplate2(target) {
    var towerId = target.attributes.id;

    var def = request({
        url: "....myServerFile.php",
        content: {
                 ...
        },
        handleAs: 'json',
        callbackParamName: 'callback',
        load: resp => {
            var markerInfo = resp.markerInfo;
            var html = "<a href=" + markerInfo.url + ">" + markerInfo.title + "</a>";
            console.log(html);

            return domConstruct.toDom(html);
        }
    });
}

....
self.map.on("load", init);
function init() {
...   
   var infoWindow = new InfoWindow({}, domConstruct.create("div", null, this.root));
   infoWindow.startup();
   this.setInfoWindow(infoWindow);
   this.infoWindow.resize(625, 240);

}

When I click the point , the infoWindow is shown but only for time. The next time I click on the point, the infoWindow
is not shown
0 Kudos