Update graphic geometry on 4.0

6383
7
05-13-2016 12:03 PM
DavidMeza
New Contributor II


In the previous API version I was able to update the geometry of a graphic using the setter (e.g. myGraphic.setGeometry(new Point([lon, lat])) ). In the current version, this functionality has been replaced by watchers/observers, but it seems this is missing on graphics. I've tried:

myGraphic.geometry = new Point([lon, lat])); // The obvious one

// And all these other ones...
myGraphic.geometry.update(lon,lat);
myGraphic.geometry.latitude = lat;
myGraphic.geometry.longitude = lon;
myGraphic.geometry.setLatitude(lat);
myGraphic.geometry.setLongitude(lon);
// Same methods using x and y, etc...

This will work if you haven't added the graphic to the map / graphicsLayer, but once you do so it is stuck at that position, no matter what method you use to update the geometry. In the meantime, I've implemented a workaround where I remove the old graphic and add a new one with the new geometry, but this is not desirable since it causes a momentary flash on the screen where there are no graphics. 

Tags (3)
0 Kudos
7 Replies
TJRockefeller
New Contributor III

I have almost the same question posted on gis stackexchange here How do you change a GraphicsLayer's geometry in the ArcGIS API for Javascript 4.0 - Geographic Infor... I came to a similar workaround, and I'm also curious if there is a better way to do this.

If the momentary flash where there are no graphics is your main concern, have you tried adding your new geometry first then removing the old geometry, so instead of briefly having no graphics you will briefly have two graphics?

SteveCole
Frequent Contributor

Unless I'm reading it wrong, it looks like it's graphic.setAttribute under the 4.0 API

graphic.setAttribute("geometry",aGeom);

0 Kudos
TJRockefeller
New Contributor III

I tried that out, and it does change the geometry of the graphic, but if the graphic has already been added to the map, this change is not reflected in the map.

Also, I'm not sure why there is a need for the setAttribute method because you can just as easily do the following

graphic.geometry = aGeom;

0 Kudos
SteveCole
Frequent Contributor

Hah, that's funny because in another thread about 4.0 I brought up the fact that either featureLayer.redraw or featureLayer.refresh was no longer present (and not listed under "coming soon"). ESRI's response was that the API "should" be smart enough to redraw/refresh once things change. I wonder if that's the same case here.

(And later in my other thread it was mentioned that redraw/refresh would return in a later API version)

0 Kudos
ReneRubalcava
Frequent Contributor

Right now you should be able to do this.

var g = graphic.clone();
g.geometry = newGeometry;
graphicsLayer.remove(graphic);
graphicsLayer.add(g);
JonLynch
New Contributor

I there likely to be any future progress on this? I am still having the same issue with 4.3 nearly a year after the original question. In particular I was hoping that an open popup would update as a graphic's attributes and geometry were updated.

0 Kudos
ThomasSolow
Occasional Contributor III

I haven't noticed any progress in this area.  My advice would be to wrap this functionality in functions.  For example:

function updateGeometry(view, graphic, newGeometry){
   // get layer.  either the graphic is in its own layer or it's
   // on the view' graphic layer
   var lyr = graphic.layer || view.graphics;

   // clone old graphic and edit geometry
   var newGraphic = graphic.clone();
   newGraphic.geometry = newGeometry;

   // remove old graphic, add new graphic
   lyr.remove(graphic);
   lyr.add(newGraphic);
}

In terms of updating the popup, I would do that by hand as well.  You can programmatically open popups with view.popupManager._showPopup({graphic: <graphic>, mapPoint: <point geometry>})

Using that you could write a function like this:

// to be called after your graphic updates and you want
// the updates to be reflected in the pop up
updatePopup(view, graphic){
  // assuming this graphic has a point geometry
  view.popupManager._showPopup({graphic: graphic, mapPoint: graphic.geometry});
}