0

I need to go through a list of objects to find the element and add a new element to the root, I can scroll through the list and find the element, but I can not add to the correct level

var data = [

    {
        "id": 1
    },
    {
        "id": 2
    },
    {
        "id": 3
    },
    {
        "id": 4,
        "children": [
            {
                "id": 6
            },
            {
                "id": 7                    
            }
        ]
    },
    {
        "id": 5
    }

];

function findById(data, id, element) {
    function iter(a) {
        if (a.id === id) {
            a.push(element); // ERROR
            result = a;
            return true;
        }
        return Array.isArray(a.children) && a.children.some(iter);
    }
    var result;
    data.some(iter);
    return result
}


var element = {
    "children": [{"id": 6}]
};

findById(data, 5, element);

document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');

https://jsfiddle.net/4nrsccnu/

Elvis Reis
  • 155
  • 4
  • 12
  • 1
    a.push does nothing because it isn't an array. Try pushing to the array. – Namaskar Aug 15 '17 at 01:08
  • 1
    `a.push` throws error because `a` is object not containing array. You need to use `Array.indexOf` to get the location of `a` in `data`. Then refer to: https://stackoverflow.com/questions/586182/how-to-insert-an-item-into-an-array-at-a-specific-index – S. Walker Aug 15 '17 at 01:15
  • You may be trying to do this though: `a.children.push` instead of `a.push` This will, in your example make the object with id of 5 have children with element of id 6. – S. Walker Aug 15 '17 at 01:19
  • What is the result you're trying to get? `{ "id": 5, "children": [ {"id": 6} ] }`? – Barmar Aug 15 '17 at 01:27

3 Answers3

1

You cannot push, because a is an object. However, you can simply add the desired property (in your case, children), and then assign it a value (in your case, the element).

var data = [

    {
        "id": 1
    },
    {
        "id": 2
    },
    {
        "id": 3
    },
    {
        "id": 4,
        "children": [
            {
                "id": 6
            },
            {
                "id": 7                    
            }
        ]
    },
    {
        "id": 5
    }

];

function findById(data, id, element) {
    function iter(a) {
        if (a.id === id) {
            a.children = element;  // Add property 'children'
            result = a;
            return true;
        }
        return Array.isArray(a.children) && a.children.some(iter);
    }
    var result;
    data.some(iter);
    return result
}

// remove property name from element, as that is being added in the function
var element = [
    {"id": 6}
];

findById(data, 5, element);

document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
Chava Geldzahler
  • 3,605
  • 1
  • 18
  • 32
1

Use Object.assign to merge the properties from the element object to the current object of the iteration.

var data = [

    {
        "id": 1
    },
    {
        "id": 2
    },
    {
        "id": 3
    },
    {
        "id": 4,
        "children": [
            {
                "id": 6
            },
            {
                "id": 7                    
            }
        ]
    },
    {
        "id": 5
    }

];

function findById(data, id, element) {
    function iter(a) {
        if (a.id === id) {
            Object.assign(a, element);
            result = a;
            return true;
        }
        return Array.isArray(a.children) && a.children.some(iter);
    }
    var result;
    data.some(iter);
    return result
}


var element = {
    "children": [{"id": 6}]
};

findById(data, 5, element);

console.log(data);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I need a structure that will mount a tree of objects, I got this way where you pass the parent id and the element to be inserted, could you please evaluate if this is the best way to do it. https://jsfiddle.net/5ajxhwx3/2/ – Elvis Reis Aug 15 '17 at 08:57
  • 1
    That seems fine. The `element` parameter to the function is different from what you showed in the question. It means the function can only add children, not other properties, but it works to add additional children to node that already has children. – Barmar Aug 15 '17 at 15:57
  • Yes and for that same add children and sibling to the elements – Elvis Reis Aug 16 '17 at 10:22
1

The push function is used for arrays, not to object. Check for details https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push.

If you want to add a single keypair to your object, you can use Object.keys and Object.values. Like this:

function findById(data, id, element) {
    function iter(a) {
        if (a.id === id) {
            var key = Object.keys(element)[0];
            var value = Object.values(element)[0];
            a[key] = value;
            result = a;
            return true;
        }
        return Array.isArray(a.children) && a.children.some(iter);
    }

    var result;
    data.some(iter);
    return result;
}