Hey @qlmoffat!
I took a stab at your question this afternoon and ran into a similar thing. We basically need some sort of recursive search. I just got it to work with multiple levels of nesting (tested with 1-5).
My code is ugly and inefficient (big O = ) and will break if a child is missing either a parentId or parentName (though this can be pretty easily fixed), but just in case this is helpful for anyone, here it is!
const data = [
{name: 'epi', id: 1},{name: 'barley', id: 6}, {name: 'sparta', id: 2, parentId: 1, parentName: 'epi'},{name: 'nova', id: 3, parentId: 1, parentName: 'epi'}, {name: 'bao', id: 4, parentId: 3, parentName: 'nova'}, {name: 'larry', id: 5}, {name: 'monkey', id: 7, parentId: 4, parentName: 'bao'}
];
const formatted_data = []
function nodeSearch(currentArr, loneChild, found = false, level=0) {
if (found) return currentArr;
if (level > currentArr.length) return 'never found';
for (let i = 0; i < currentArr.length; i++) {
if (currentArr[i].value == loneChild.parentId) {
found = true;
const formattedChild = {'label': loneChild.name, 'value': loneChild.id}
currentArr[i].children ? currentArr[i].children.push(formattedChild) : currentArr[i].children = [formattedChild]
nodeSearch(currentArr, loneChild, true);
} else if (currentArr[i].children){
return nodeSearch(currentArr[i].children, loneChild, false, 0)
}
}
return found ? currentArr : nodeSearch(currentArr, loneChild, false, ++level);
}
for (let i = 0; i < data.length; i++) {
let each_obj = data[i];
let new_obj = {'label': each_obj.name, 'value': each_obj.id};
if (!each_obj.parentId) { //has no parent
formatted_data.push(new_obj) //add to final obj
} else if (each_obj.parentName && JSON.stringify(formatted_data).indexOf(each_obj.parentName) == -1 ) { //has parent, but parent not yet listed
let new_parent_obj = {'label': each_obj.parentName, 'value': each_obj.parentId, 'children':[new_obj]} //create new parent with new child
formatted_data.push(new_parent_obj) //add new parent + new child to final obj
} else if (each_obj.parentName && JSON.stringify(formatted_data).indexOf(each_obj.parentName) > -1) { //has parent, and parent already listed _somewhere_
nodeSearch(formatted_data, each_obj);
}
}
return formatted_data;