1

I have searched for a way to remove single object from an array of objects if id variable equals the id of an object.

I use the array to know which checkboxes are selected so that related information will be collected for further processing.

example: https://jsbin.com/vicerewevi/edit?html,js,output

Error that I get when I select the checkboxes fast:

Uncaught TypeError: Cannot read property 'id' of undefined
    at vicerewevi.js:33
    at Function.each (jquery-3.1.0.js:368)
    at HTMLInputElement.<anonymous> (vicerewevi.js:32)
    at HTMLInputElement.dispatch (jquery-3.1.0.js:5110)
    at HTMLInputElement.elemData.handle (jquery-3.1.0.js:4918)

above error occurs on the line if value.id == id:

// if checkbox is checked, add object to array and if unchecked remove object by 'id' from array
$('.checkbox').change( function(){

    var id = parseInt($(this).attr('data-id'))
    var foo = $(this).parent().siblings().find('#foo').val()
    var bar = $(this).parent().siblings().find('#bar').val()

    if($(this).prop('checked')) {
        var obj = {'id': id, 'foo': foo, 'bar': bar}
        jsonobjects.push(obj)
    } else {
        $.each(jsonobjects, function( index, value ) {
            if (value.id == id ) {
                jsonobjects.delete(index)
            }
        });
    }
    countChecked() // update count of checkboxes
    console.log(JSON.stringify(jsonobjects))
  $('#output').html(JSON.stringify(jsonobjects, null, ""))
});

I found this code below on SO (never worked with custom prototypes before) that I tried:

Array.prototype.delete = function(pos){
    this[pos] = undefined;
    var len = this.length - 1;
    for(var a = pos;a < this.length - 1;a++){
      this[a] = this[a+1];
    }
    this.pop();
  }
Xenioz
  • 49
  • 2
  • 12
  • Have you tried `value.getAttribute("id") == id` in place of `value.id == id` ? In case it's an element ? –  Jul 01 '18 at 09:48
  • By the way, instead of that weird `delete` method, you could just do `jsonobjects.splice(index, 1)` – Jonas Wilms Jul 01 '18 at 09:48
  • @JonasW. thanks, I also added hasownproperty in simple for loop instead of $.each to check if element in array is not a array function – Xenioz Jul 01 '18 at 10:20

4 Answers4

2

Because you delete entries from your array, the next time you iterate over it, you will get a value that is undefined for that particular "gap" in your array. Obviously, that does not have an id property.

To solve this, do not use delete, but use filter to create a new, filtered array, which will not have such gaps.

Replace:

    $.each(jsonobjects, function( index, value ) {
        if (value.id == id ) {
            jsonobjects.delete(index)
        }
    });

...with:

    jsonobjects = jsonobjects.filter(function( value ) {
        return value.id !== id;
    });

Or, if you want to stick to jQuery methods, use $.grep:

    jsonobjects = $.grep(jsonobjects, function( value ) {
        return value.id !== id;
    });
trincot
  • 317,000
  • 35
  • 244
  • 286
2

I have searched for a way to remove single object from an array of objects if id variable equals the id of an object.

const arr = [
  { id: 0 },
  { id: 1 },
  { id: 2 },
  { id: 3 },
  { id: 4 },
  { id: 5 }
];

const removeById = (arr, id) => arr.filter(e => e.id !== id);

const no2 = removeById(arr, 2);
const no5 = removeById(arr, 5);

console.log(no2);
console.log(no5);
Olian04
  • 6,480
  • 2
  • 27
  • 54
2

Make use of the Array.filter method and reassign jsonobjects to the filtered array like so instead of the delete method you created

jsonObjects = jsonObjects.filter((value, index) => { return value.id !== id; }) I hope this helps

Johnbosco
  • 73
  • 7
0

This worked for me when I tried solution on this awnser For..In loops in JavaScript - key value pairs

for (var k in jsonobjects){
    if (jsonobjects.hasOwnProperty(k)) {
        if (jsonobjects[k].id == id) {
            jsonobjects.splice(k, 1)
        }
    }
}
Xenioz
  • 49
  • 2
  • 12
  • This could leave an entry in the array if `jsonobjects` has two consecutive objects that both have the `id` value you want to remove. In that case only the first of the two will be deleted, since `splice` moves all remaining elements one index position backward, and the `for` loop will not revisit the same index which now has the next item. See for instance [this question & answer](https://stackoverflow.com/questions/16217333/remove-items-from-array-with-splice-in-for-loop). – trincot Jul 01 '18 at 11:29