dmathisen
dmathisen

Reputation: 2342

Removing an item from a multidimentional Javascript array, based on property value

I'm using KnockoutJS and have a multidimensional observable array (object?):

self.navItems = ko.observableArray([
    { name: "test1", children: [
        { name: "test1child1", children: [] },
        { name: "test1child2", children: [] }
    ]},
    { name: "test2", children: [] },
]);

I'd like to be able to remove one of the objects, based on a property value. In other works, I'd like to do something this:

removeNavItem("test1child2");

I've written a function but can't get it to work because it's looking for 'test1child2' as a property, not a value.

self.removeNavItem = function (itemName) {
    var item = ko.utils.arrayFirst(self.navItems(), function (item) {
        if (item.name === itemName) { // this seems to work correctly
            delete self.navItems[itemName]; // this doesn't, because it tests property, not value
        }
    });
};

jsfiddle link

EDIT:

I didn't know about KO's built in remove/removeAll methods.

Thanks to the commentors below, I have it partially working but when I try to remove something inside of children[], it removes the entire parent as well.

removeNavItem = function (itemName) {
    var items = self.navItems.remove(function (item) {
        for (i = 0; i < item.children.length; i++) {
            if (item.children[i].name === itemName) {
                return item.children[i].name;
            }
        }
        return item.name === itemName;
    });
};

updated jsfiddle

Upvotes: 2

Views: 159

Answers (3)

Nate
Nate

Reputation: 16898

There's an easier way to do this. Knockout provides a remove() that can use a function to remove the matching items:

self.removeNavItem = function (itemName) {
    var items = self.navItems.remove( function (item) { 
        return item.name === itemName; 
    });
};

(It's mentioned in the 'Remove and RemoveAll' section in the observableArrays documentation)

Upvotes: 1

Paul Manzotti
Paul Manzotti

Reputation: 5147

If you want to be able to use it on any level, then pass in the array that you want to remove it from:

self.removeNavItem = function (obsArray, itemName)
{
    obsArray.remove(function(item) { return item.name === itemName });
};

Then you can call this on each element:

click: function() { $root.removeNavItem($parent.children, $data.name); }

I've updated your jsfiddle, and it works, though you have to make all children arrays observable arrays for it to work.

Upvotes: 1

misoukrane
misoukrane

Reputation: 304

I think you will need a function that make a search on n level of recursion

 function del(obj,val){
   $.each(obj,function(i,j){
       if(j['name'] == val){
          delete(j);
          return false;
       }else if(j['children'].length!=0){
           del(j['children'],val);
         }
   })

 }

this function take two arguments your object and the value to search, you can modify it to suit your case.

Upvotes: 1

Related Questions