// E.g. I want to find element with id='4'
// and add children: [{ id:'5', name: 'Child - 4' }]
const data = {
id: 'root',
name: 'Parent',
children: [
{
id: '1',
name: 'Child - 1',
},
{
id: '3',
name: 'Child - 3',
children: [
{
id: '4',
name: 'Child - 4',
},
],
},
],
};
function addChildrenToParentByParentId(id, node, childNodes) {
let isSuccess = false;
const { children } = node;
if (node.id === id) {
// because `childNodes` can be both a single node or a node list.
childNodes = [].concat(childNodes);
// prevent child node duplicates by ...
node.children =
((Array.isArray(children) && children) || []).filter(child =>
// ... skipping older nodes which feature newer ids ...
childNodes.every(node => node.id !== child.id)
// ... and always concatenating the most recent child nodes.
).concat(childNodes);
isSuccess = true;
} else if (Array.isArray(children)) {
// recursion ... but using `Array.prototype.some`
// in order to achieve both an early exit and the
// indication whether children could be added.
isSuccess = children.some(child =>
addChildrenToParentByParentId(id, child, childNodes)
);
}
return isSuccess;
}
// fails ... provides a node list
console.log(
"addChildrenToParentByParentId('2', data, [{ id:'5', name: 'Child - 4' }]) ...",
addChildrenToParentByParentId('2', data, [{ id:'5', name: 'Child - 4' }])
);
console.log(data);
// succeeds ... provides a single node
console.log(
"addChildrenToParentByParentId('4', data, { id:'5', name: 'Child - 4' }) ...",
addChildrenToParentByParentId('4', data, { id:'5', name: 'Child - 4' })
);
console.log(data);
// succeeds ... provides a node list
console.log(
"addChildrenToParentByParentId('3', data, [{ id:'6', name: 'Child - 4' }, { id:'7', name: 'Child - 4' }]) ...",
addChildrenToParentByParentId('3', data, [{ id:'6', name: 'Child - 4' }, { id:'7', name: 'Child - 4' }])
);
console.log(data);
// succeeds ... provides a single node ... prevents duplicates
console.log(
"addChildrenToParentByParentId('3', data, { id:'6', name: 'Child - XX' }) ...",
addChildrenToParentByParentId('3', data, { id:'6', name: 'Child - XX' })
);
console.log(data);
.as-console-wrapper { min-height: 100%!important; top: 0; }