Select to view content in your preferred language

remove previous graphic

9825
30
04-09-2012 10:37 AM
evanpicard
Emerging Contributor
as many have read by now, I've got a data grid populated by a spatial query, and corresponding points in a map (red circles).

when you click on a record in the table, I would like a graphic added to the map to highlight (green circle) an already existing point(red circle). when you click a different record in the grid, i would like the first highlighter to disappear, and a new one appear.
right now, things go 2 ways, either the selected point never clears, and it adds more and more graphic points, or the last of the red query point graphics to be drawn disappears. 

how do i specifically remove a graphic from selectedRepGraphic, not just the last graphic added, which is what happens now?


      function onRowClickHandler(evt){
        var clickedRep = grid.getItem(evt.rowIndex).rep_no;
        var selectedRep;
        var selectedRepSymbol = new esri.symbol.SimpleMarkerSymbol();
        selectedRepSymbol.style = esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE;
        selectedRepSymbol.setSize(10);
        selectedRepSymbol.setColor(new dojo.Color([0,255,0, 1]));   
        dojo.forEach(map.graphics.graphics,function(graphic){
          if((graphic.attributes) && graphic.attributes.rep_no === clickedRep){
            selectedRep = graphic;
            var selectedRepGraphic = new esri.Graphic(selectedRep, selectedRepSymbol);
            selectedRepGraphic.setSymbol(selectedRepSymbol);
            
            var selInfoTemplate = new esri.InfoTemplate("Sales Rep: ${NAME}", ("${*}")); //"Rep # : ${rep_no}", "Address : ${ADDR1}");
            map.infoWindow.setTitle(selectedRepGraphic.getContent("${NAME}"));
            map.infoWindow.setContent(selectedRepGraphic.getContent("Sales Rep: ${NAME}", "Rep #: ${rep_no}", "Address : ${ADDR1}"));
            selectedRepGraphic.setInfoTemplate(selInfoTemplate);
            map.infoWindow.show(selectedRepGraphic.geometry);

            if (selectedRepGraphic != undefined){
              map.graphics.remove(map.graphics.graphics[map.graphics.graphics.length - 1]);
            };
            
            map.graphics.add(selectedRepGraphic);
            

            return;
          };
        });
            return;
      };
0 Kudos
30 Replies
JeffPace
MVP Alum
You are doing everything correctly.  If you can log map.spatialReference your scope is correct

its amazing that map.graphics.clear() works but map.graphics.remove(g), when g is a valid graphic, does not.

Thank you for the help thus far.
Im going to be bald by the end of the day if I keep up all this hairpulling...


map.graphics.clear(); works, (and worked previously) but map.graphics.remove(g); does nothing.
as a test, within the IF i tried console.log(map.spatialReference), and it reported back to the console just fine.

what version of the API are you on? do you get any error in firebug?



      function onClicker(evt){
        dojo.forEach(map.graphics.graphics, function(g) {
          if ( g && g.id === "highlight" ) {
            //remove graphic with specific id
            map.graphics.remove(g); 
            console.log(map.spatialReference)
          }
        }, this);
        identifyTaskReps = new esri.tasks.IdentifyTask("http://172.26.197.91/ArcGIS/rest/services/IndivTerritoriesOnly/SalesReps_simple/MapServer/");
        identifyParamsReps = new esri.tasks.IdentifyParameters();
        identifyParamsReps.tolerance = 5;
        identifyParamsReps.returnGeometry = true;
        identifyParamsReps.layerIds = [0];
        identifyParamsReps.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
        identifyParamsReps.width  = map.width;
        identifyParamsReps.height = map.height;
        identifyParamsReps.geometry = evt.mapPoint;
        identifyParamsReps.mapExtent = map.extent;
        var deferred = identifyTaskReps.execute(identifyParamsReps);
        deferred.addCallback(function(response){
          if (response.length > 0) {
//           console.log("response length ",  response.length)
//           response is an array of identify result objects    
//           Let's return an array of features.
            return dojo.map(response, function(result){
              var selFeature = result.feature;
              var selFeatureSymbol = new esri.symbol.SimpleMarkerSymbol();
              selFeatureSymbol.style = esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE;
              selFeatureSymbol.setSize(10);
              selFeatureSymbol.setColor(new dojo.Color([0,255,0, 1]));

              selFeature.setSymbol(selFeatureSymbol);

              selFeature.attributes.layerName = result.layerName;
              var infoTemplate = new esri.InfoTemplate();
              selFeature.setInfoTemplate(infoTemplate);
              var name = selFeature.attributes.NAME;
              var rep_no = selFeature.attributes.rep_no;
              var address = selFeature.attributes.ADDR1;
              var city = selFeature.attributes.CITY;
              var state = selFeature.attributes.ST_ABBR;
              var zipcode = selFeature.attributes.ZIP_CODE;
              var leader = selFeature.attributes.Ldr_type;
              var prez = selFeature.attributes.PCText;                        
              var content = "<b>Rep # : </b>" + rep_no + "<br><b>Address : </b>" + address + "<br><b>City : </b>" + city + "<br><b>State : </b>" + state + "<br><b>Zip : </b>" + zipcode + "<br><b> Leader : </b>" + leader + "<br><b>Presidents Club :</b>" + prez;
              var title = "<b>Name : </b>" + name;            
              map.infoWindow.setTitle(title);
              map.infoWindow.setContent(content);            
              map.graphics.add(selFeature);  
              map.infoWindow.show(selFeature.geometry);       

              highlightGraphic = new esri.Graphic(selFeature, selFeatureSymbol);
              highlightGraphic.id = "highlight";
              highlightGraphic.setSymbol(selFeatureSymbol);
              map.graphics.add(highlightGraphic);
            });
         };
       });
      };


evanpicard
Emerging Contributor
if i log the graphic
console.log(g)


I get the following results:

a
_extent: a
_graphicsLayer: null
_shape: null
attributes: Object
geometry: a
id: "highlight"
infoTemplate: a
symbol: a
__proto__: Object
0 Kudos
evanpicard
Emerging Contributor
A note:
if I log the graphics before the IF statement
        
dojo.forEach(map.graphics.graphics, function(g){
          console.log(g)
          if (g && g.id === "highlight") {
            //remove graphic with specific id
            console.log(g);
            map.graphics.remove(g);
            console.log(map.spatialReference)
          }
        }, this);


I get 6 results in the console on the first click -

  • the point (2 graphics) that is the result of the address locator

  • the buffer ring

  • the query results (2 graphics)

  • the added graphic from clicking


clue?
derekswingley1
Deactivated User
clue?


None. How about implementing the other two things I suggested:  use an the graphic's attributes object to assign your id (probably won't change anything) and don't use "this" as the 3rd arg to dojo.forEach.

Alternatively, how about using a separate graphics layer for your highlight graphics? That way, you add graphics to your highlight layer and can clear it when needed. This would eliminate the need for this type of manual filtering.
0 Kudos
evanpicard
Emerging Contributor
doesnt

              highlightGraphic = new esri.Graphic(selFeature, selFeatureSymbol);
              highlightGraphic.id = "highlight";
              highlightGraphic.setSymbol(selFeatureSymbol);
              map.graphics.add(highlightGraphic);


create a separate graphics layer?
0 Kudos
evanpicard
Emerging Contributor
getting closer?

      function onClicker(evt){
        identifyTaskReps = new esri.tasks.IdentifyTask("http://172.26.197.91/ArcGIS/rest/services/IndivTerritoriesOnly/SalesReps_simple/MapServer/");
        identifyParamsReps = new esri.tasks.IdentifyParameters();
        identifyParamsReps.tolerance = 7;
        identifyParamsReps.returnGeometry = true;
        identifyParamsReps.layerIds = [0];
        identifyParamsReps.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
        identifyParamsReps.width  = map.width;
        identifyParamsReps.height = map.height;
        identifyParamsReps.geometry = evt.mapPoint;
        identifyParamsReps.mapExtent = map.extent;
        var deferred = identifyTaskReps.execute(identifyParamsReps);
        deferred.addCallback(function(response){
          if (response.length > 0) {
//           console.log("response length ",  response.length)
//           response is an array of identify result objects    
//           Let's return an array of features.
            return dojo.map(response, function(result){
              var selFeature = result.feature;
              var selFeatureSymbol = new esri.symbol.SimpleMarkerSymbol();
              selFeatureSymbol.style = esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE;
              selFeatureSymbol.setSize(10);
              selFeatureSymbol.setColor(new dojo.Color([0,255,0, 1]));

              selFeature.setSymbol(selFeatureSymbol);

              selFeature.attributes.layerName = result.layerName;
              var infoTemplate = new esri.InfoTemplate();
              selFeature.setInfoTemplate(infoTemplate);
              var name = selFeature.attributes.NAME;
              var rep_no = selFeature.attributes.rep_no;
              var address = selFeature.attributes.ADDR1;
              var city = selFeature.attributes.CITY;
              var state = selFeature.attributes.ST_ABBR;
              var zipcode = selFeature.attributes.ZIP_CODE;
              var leader = selFeature.attributes.Ldr_type;
              var prez = selFeature.attributes.PCText;                        
              var content = "<b>Rep # : </b>" + rep_no + "<br><b>Address : </b>" + address + "<br><b>City : </b>" + city + "<br><b>State : </b>" + state + "<br><b>Zip : </b>" + zipcode + "<br><b> Leader : </b>" + leader + "<br><b>Presidents Club :</b>" + prez;
              var title = "<b>Name : </b>" + name;            
              map.infoWindow.setTitle(title);
              map.infoWindow.setContent(content);            
              map.graphics.add(selFeature);  
              map.infoWindow.show(selFeature.geometry);       

              highlightGraphic = new esri.Graphic(selFeature, selFeatureSymbol);
              highlightGraphic.attributes.id = "highlight";
              highlightGraphic.setSymbol(selFeatureSymbol);
              
              dojo.forEach(map.graphics.graphics, function(g){
                if ( g.attributes && g.attributes.id === "highlight" ) {
                  //remove graphic with specific id
                  map.graphics.remove(g);
                }
              });
              map.graphics.add(highlightGraphic);
            });
         };
       });
      };


I moved the dojo.forEach to the end, it actually works.
BUT
on the SECOND click, I get a type error.
0 Kudos
derekswingley1
Deactivated User
doesnt

              highlightGraphic = new esri.Graphic(selFeature, selFeatureSymbol);
              highlightGraphic.id = "highlight";
              highlightGraphic.setSymbol(selFeatureSymbol);
              map.graphics.add(highlightGraphic);


create a separate graphics layer?


No, that adds a graphic to the map's default graphics layer (every esri.Map automatically has a graphics layer).

What I was suggesting was that you could create a new esri.layers.GraphicsLayer and add your highlight graphics to that. That way, you don't need to assign new attributes to graphics, filter and remove specific graphics. When you want to clear your graphics used to highlight feature(s), you call highlightLayer.clear(). Instead of adding your graphics to using map.graphics.add(graphic), you would use highlightLayer.add(graphic). You could use a global to keep track of your highlight layer(bad) or you could get to it using map.getLayer() (good).
0 Kudos
derekswingley1
Deactivated User
<snip> ... I get a type error.


What does firebug report as the error?
0 Kudos
evanpicard
Emerging Contributor
What does firebug report as the error?


from firebug:

TypeError: g is undefined
(undefined="(void 0)", undefined="7", undefined="[object Array]")findarep.html (line 417)
(undefined="[object Array]", undefined="(function (g) {if (g.at....graphics.remove(g);}})")?v=2.8 (line 14)
(undefined="[object Object]", undefined="0", undefined="[object Array]")findarep.html (line 416)
.setSymbol(undefined="selFeatureSymbol);dojo....h(map.graphics.graphics", undefined=" function (g) {if (g.at...dd(highlightGraphic);})")?v=2.8 (line 14)
(undefined="[object Array]")findarep.html (line 384)
_144()?v=2.8 (line 14)
_142(undefined="[object Array]")?v=2.8 (line 14)
(undefined="[object Array]")?v=2.8 (line 14)
(undefined="[object Object]", undefined="[object Array]")?v=2.8 (line 48)
(undefined="[object Array]", undefined=""onComplete"", undefined="(void 0)", undefined="[object Object]")?v=2.8 (line 48)
(undefined="[object Object]", undefined="[object Object]", undefined="(void 0)", undefined="(void 0)", undefined="[object Object]")?v=2.8 (line 48)
(undefined="[object Object]", undefined="[object Object]", undefined="(void 0)", undefined="(void 0)", undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]", undefined="[object Object]")?v=2.8 (line 48)
(undefined="[object Object]")?v=2.8 (line 48)
_144()?v=2.8 (line 14)
_142(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 48)
_144()?v=2.8 (line 14)
_142(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 14)
_144()?v=2.8 (line 14)
_142(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 14)
_144()?v=2.8 (line 14)
_142(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 14)
_144()?v=2.8 (line 14)
_142(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 14)
(undefined="[object Object]")?v=2.8 (line 48)
()?v=2.8 (line 14)
(undefined="12")?v=2.8 (line 14)
 

if ( g.attributes && g.attributes.id === "highlight" ) {


0 Kudos
derekswingley1
Deactivated User
The issue is that calling map.graphics.remove modifies the array you're looping through. Since forEach doesn't re-check how many items are in the array after each iteration, it will eventually try to access an array index that doesn't exist. You could probably work around this by checking if g exists...this might to do it:
if ( g && g.attributes && g.attributes.id === "highlight" ) {

but I think that's getting overly complicated.

Again, I would encourage you to move away from using the map's graphics layer for all graphics and use separate graphics layers for separate purposes.

One other question:  why are you returning the result of dojo.map? Do you have other code saving the result from your onClicker function?
0 Kudos