remove the last added graphic

1219
7
Jump to solution
10-09-2018 05:06 PM
GotQuestion
New Contributor II

Each time a user clicks on a list I add a new graphic on top of the clicked item.

However, I want to remove the last graphic that was created.

fyi, I can't do view.graphics.clear because before the user click I've created graphics that I need to keep.

This creates the graphic without problems.

function onListClickHandler(event) { 
const target = event.target; 
const resultId = target.getAt tribute("data-result-id");

// get the graphic corresponding to the clicked parcel
const result = resultId && graphics && graphics[parseInt(resultId,
10)]; 

var selectFillSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [111, 0, 255, 0.3],
outline: { // autocasts as new SimpleLineSymbol()
color: [0,0,0],
width: 2
}
};

var polygonGraphic = new Graphic({
geometry: result.geometry,
symbol: selectFillSymbol,
attributes: simpleFillAttributes
});

view.graphics.add(polygonGraphic);

But none of these ideas below remove the graphic

capturing the reference of the last object

var lastResult = result

view.graphics.remove(lastResult);

view.graphics.remove(graphics[parseInt(lastResultId,10)]; 

I tried adding an attribute to the new object

since result.attributes.OBJECTID works and gives back the objectid of the original clicked item. 

var simpleFillAttributes = {
Name: "newgraphic-" + result.attributes.OBJECTID
};

var polygonGraphic = new Graphic({
geometry: result.geometry,
symbol: selectFillSymbol,
attributes: simpleFillAttributes
});

and then looping through all the graphics but this give me "cannot read property Name of null"

view.graphics.forEach(function (graphic) {
if (graphic.attributes["Name"] == "newgraphic-" + result.attributes.OBJECTID) {
graphic.remove(graphic);
}
});

How can I remove the last graphic created? 

0 Kudos
1 Solution

Accepted Solutions
GotQuestion
New Contributor II

Got it working with view.graphics.some not view.graphics.graphics

The main original issue was cannot read property Name of null

and this happened because I had created some graphic objects before the user did any clicking and those objects did not contain the custom attribute of Name but my new objects did have the Name attribute.

once I added the Name attribute to all the objects the code below works fine

view.graphics.some(function (graphic) {
if (graphic.attributes["Name"] == "selected-" + lastObjectID) {
view.graphics.remove(graphic);
return true;
}
});

View solution in original post

0 Kudos
7 Replies
RobertScheitlin__GISP
MVP Emeritus

Your idea of looping through the graphics and looking for an specific attribute is definitely the way to go but your code is wrong.

view.graphics.graphics.some(function (graphic) {
  if (graphic.attributes["Name"] == "newgraphic-" + result.attributes.OBJECTID) {
    graphic.remove(graphic);
    return true;
  }
});

View.graphics is a GraphicsLayer object not the graphics inside that layer thus you need view.graphics.graphics

0 Kudos
GotQuestion
New Contributor II

thanks for your help. I'm still having problems.

when I do view.graphics.graphics.some I get   "cannot read property 'some' of undefined"

so it never does the loop

when I do view.graphics.some it goes into the loop but then I get "cannot read property Name of null"

fyi, I create the graphics fine doing view.graphics.add(polygonGraphic) not view.graphics.graphics.add

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Sorry I was confusing 3.x and 4.x properties. 

In 4.x the view.graphics is a collection. in 3.x the map.graphics is a GraphicsLayer.

So the likely issue that the view is not initialized when you are trying to loop through it's graphics then.

view.graphics.some(function(graphic, i){
  if(graphic.attributes.Name == "newgraphic-" + result.attributes.OBJECTID) {
    view.graphics.remove(graphic);
    return true;
  }
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Have you tried to console.log(view.graphics)?

0 Kudos
GotQuestion
New Contributor II

got it. thanks! btw, what is the main difference between looping with some vs forEach?

0 Kudos
KenBuja
MVP Esteemed Contributor

From the dojo documentation:

 

some() semantically answers the question “does a test hold true for at least one item in the array?” Like forEach(), some() iterates over the items in an array. However, it short circuits and returns true as soon as it encounters an item for which the provided callback returns a truthy value. If the callback doesn’t return true for any item, some() returns false.

Note: Because of the short circuiting, some() can be more efficient than forEach() when the loop is used for comparison purposes.

GotQuestion
New Contributor II

Got it working with view.graphics.some not view.graphics.graphics

The main original issue was cannot read property Name of null

and this happened because I had created some graphic objects before the user did any clicking and those objects did not contain the custom attribute of Name but my new objects did have the Name attribute.

once I added the Name attribute to all the objects the code below works fine

view.graphics.some(function (graphic) {
if (graphic.attributes["Name"] == "selected-" + lastObjectID) {
view.graphics.remove(graphic);
return true;
}
});

0 Kudos
RaoulComaduran2
New Contributor II

Greetings,

 

I am trying to run this same type of operation to remove the last added graphic to the map but my code isn't working. Would you mind pointing me in the right direction for correcting it? 

$("#btnRemovepoint").click(function () {
// alert("there were " + obsPoints.length + " points.");
clearPointForm();
obsPoints.pop();
view.graphics.some(function (graphic) {
if (graphic.attributes["Name"] == "selected-" + lastObjectID) {
view.graphics.remove(graphic);
return true;
}
});
// todo remove last point graphic
// todo remove last point from input table
});

0 Kudos