remove previous graphic

8115
30
04-09-2012 10:37 AM
evanpicard
New Contributor II
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
I do this in kind of a round about way.  ON creation I add an ID to the graphic.

this.highlightGraphic=new esri.Graphic(geometry, sym);
                        this.highlightGraphic.id="highlight";
   this.map.graphics.add(this.highlightGraphic);


Then you can

dojo.forEach(this.map.graphics.graphics, dojo.hitch(this, function (g){
                          if(g&&g.id==="highlight"){
                             //remove graphic with specific id
                              this.map.graphics.remove(g);
                            }
                    }));


does that help?

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
evanpicard
New Contributor II
Got it!
Thanks.
Can you explain what "this" is all about? I've read a few articles, and can't get my head around it.
0 Kudos
derekswingley1
Frequent Contributor
Good explanation of "this" in JS:  http://www.quirksmode.org/js/this.html

As an aside, dojo.forEach takes a third argument to specify the scope for the callback. So...you could omit that call to dojo.hitch:
dojo.forEach(this.map.graphics.graphics, function(g) {
  if( g && g.id === "highlight" ) {
    //remove graphic with specific id
    this.map.graphics.remove(g);
  }
}, this);


which is cleaner, IMO. Great info on forEach here:  http://dojotoolkit.org/documentation/tutorials/1.6/arrays/
0 Kudos
JeffPace
MVP Alum
Yes sorry you dont need the "this" my code was from within a widget we load, so it was for scoping.

Glad i helped!
0 Kudos
JeffPace
MVP Alum
wait so i post the code and derek gets credit for the answer ?? not cool derek, not cool.

🙂 😞
0 Kudos
evanpicard
New Contributor II

dojo.forEach(this.map.graphics.graphics, function(g) {
  if( g && g.id === "highlight" ) {
    //remove graphic with specific id
    this.map.graphics.remove(g);
  }
}, this);



I've got it working very nicely, I appreciate the help from both of you.  But I have a question, how would you re-write the dojo statement without the "this"?

dojo.forEach(this.map.graphics.graphics, function(g) {
  if( g && g.id === "highlight" ) {
    //remove graphic with specific id
    map.graphics.remove(g);
  }
}, this);   // <-----WHAT HAPPENS TO THIS this?


Thanks again, to BOTH OF YOU!
0 Kudos
JeffPace
MVP Alum
you will need a "this" somewhere, because you are removing the graphic from the map. 

In my sample I use dojo.hitch  to explicitly hitch the new function(g) into the larger scope (this) so that i have access to this.map

In derek's sample, he more eloquently realizes that dojo.forEach can take scope as a third argument, so his code becomes

dojo.forEach(graphic, function, scope) - which is the "this" at the end, allowing him to skip the hitch statement.

Both have the same effect

The only way you could completely avoid using this would be to pass your map object into your function.  I dont think that would be very efficient.
0 Kudos
derekswingley1
Frequent Contributor
wait so i post the code and derek gets credit for the answer ?? not cool derek, not cool.

🙂 😞


Jeff should absolutely get credit for answering this thread...I just piggy-backed on what he was saying :).
0 Kudos
JeffPace
MVP Alum
Jeff should absolutely get credit for answering this thread...I just piggy-backed on what he was saying :).


I was just teasing Derek.  Thats why I love these forums, lots of people working together to help each other.  It is a pleasure to be part of this community.
0 Kudos