I have this kind of array (i call it categories, these have childCats too)
var cats = [
{
"id": 1,
"name": "A",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": [
{
"id": 2,
"name": "B",
"parentCategoryId": 1,
"parentCategory": null,
"childCategories": [
{
"id": 3,
"name": "C",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
},
{
"id": 4,
"name": "D",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
},
{
"id": 5,
"name": "E",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
}
]
}
]
},
{
"id": 66,
"name": "BLA",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": []
},
];
What i now need is to get an array with checked items (and its parents)
This means, i checked only "C", i get:
[
{
"name": "A",
"childCategories": [
{
"name": "B",
"childCategories": [
{
"name": "C",
"childCategories": []
}
]
}
]
}
]
if i checked "C" and "D":
var cats = [
{
"name": "A",
"childCategories": [
{
"name": "B",
"childCategories": [
{
"name": "C",
"childCategories": []
},
{
"name": "D",
"childCategories": []
}
]
}
]
},
];
and for "B" this:
var cats = [
{
"name": "A",
"childCategories": [
{
"name": "B",
"childCategories": []
}
]
},
];
What i currently have (and it feels like a mess) is that: (result in console.log(..))
console.clear();
var checkedInterests = ['C'];
var checkedInterestsForDisplay = [];
var getInterestsForDisplay = function(arr) {
for (var a of arr) {
if (checkedInterests.includes(a.name)) {
a.childCategories = [];
checkedInterestsForDisplay.push(a);
//also if a child is checked, the parent should be expanded
var getParents = function(arrayToFindParent, parentIdToFind) {
for (var aTFP of arrayToFindParent) {
if (aTFP.id == parentIdToFind) {
aTFP.childCategories = checkedInterestsForDisplay;
checkedInterestsForDisplay = [aTFP];
//again check if it has parents
getParents(cats, aTFP.parentCategoryId);
} else {
getParents(aTFP.childCategories, parentIdToFind);
}
}
}
getParents(cats, a.parentCategoryId);
}
getInterestsForDisplay(a.childCategories);
}
}
getInterestsForDisplay(cats);
console.log('checkedInterestsForDisplay', checkedInterestsForDisplay);
<script>
var cats = [{
"id": 1,
"name": "A",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": [{
"id": 2,
"name": "B",
"parentCategoryId": 1,
"parentCategory": null,
"childCategories": [{
"id": 3,
"name": "C",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
},
{
"id": 4,
"name": "D",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
}
]
}]
},
{
"id": 66,
"name": "BLA",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": []
},
];
</script>
this works oky, but if
var checkedInterests = ['C','D'];
i get
Maximum call stack size exceeded
Here's a simplified recursive approach. I assume the result should be the same if you check A and C as if you just checked C.
console.clear();
var checkedInterests = ['B','BLA'];
const getInterestsForDisplay = (arr) =>
arr.reduce((acc, el) => {
// get a list of checked children (recursive call)
const children = el.childCategories?.length
? getInterestsForDisplay(el.childCategories)
: [];
// either this element is checked, or a child is checked, to be added to output.
if (checkedInterests.includes(el.name) || children.length) {
acc.push({...el, childCategories: children});
}
return acc;
}, []);
const checkedInterestsForDisplay = getInterestsForDisplay(cats);
console.log(checkedInterestsForDisplay);
<script>
var cats = [{
"id": 1,
"name": "A",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": [{
"id": 2,
"name": "B",
"parentCategoryId": 1,
"parentCategory": null,
"childCategories": [{
"id": 3,
"name": "C",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
},
{
"id": 4,
"name": "D",
"parentCategoryId": 2,
"parentCategory": null,
"childCategories": []
}
]
}]
},
{
"id": 66,
"name": "BLA",
"parentCategoryId": null,
"parentCategory": null,
"childCategories": []
},
];
</script>