Reputation: 111
I want to find an element inside a tree by its property value and then move back to the beginning of the tree and set isExpanded
property of each of element's parents to true
using JS.
So I have this object:
elementsArray = [
{
name: 'test_1',
isExpanded: false,
expandElements: [
{
name: 'test_1_1',
isExpanded: false,
expandElements: [
{
name: 'test_1_1_1'
},
{
name: 'test_1_1_2'
}
]
},
{
name: 'test_1_2',
isExpanded: false,
expandElements: [
{
name: 'test_1_2_1'
},
{
name: 'test_1_2_2'
}
]
}
]
},
{
name: 'test_2',
isExpanded: false,
expandElements: [
{
name: 'test_2_1',
isExpanded: false,
expandElements: [
{
name: 'test_2_1_1'
},
{
name: 'test_2_1_2'
}
]
},
{
name: 'test_2_2',
isExpanded: false,
expandElements: [
{
name: 'test_2_2_1'
},
{
name: 'test_2_2_2'
}
]
}
]
}
]
I want to find the element, which has property name: 'test_2_2_1'
and set isExpanded
property of each of its parents to true.
How it should work:
expandParentElements(elementsArray, 'test_2_2_1')
elementsArray
changed to:elementsArray = [
{
name: 'test_1',
isExpanded: false,
expandElements: [
{
name: 'test_1_1',
isExpanded: false,
expandElements: [
{
name: 'test_1_1_1'
},
{
name: 'test_1_1_2'
}
]
},
{
name: 'test_1_2',
isExpanded: false,
expandElements: [
{
name: 'test_1_2_1'
},
{
name: 'test_1_2_2'
}
]
}
]
},
{
name: 'test_2',
isExpanded: **true**,
expandElements: [
{
name: 'test_2_1',
isExpanded: false,
expandElements: [
{
name: 'test_2_1_1'
},
{
name: 'test_2_1_2'
}
]
},
{
name: 'test_2_2',
isExpanded: **true**,
expandElements: [
{
name: 'test_2_2_1'
},
{
name: 'test_2_2_2'
}
]
}
]
}
]
By now i've managed to only recursively move inside tree and find proper element. Here how it looks like:
let expandParentElements = (array, searchName) => {
return array.map(item => {
if (item.name === searchName) {
return item
} else if (item.expandElements) {
return expandParentElements(item.expandElements, searchName)
}
})
}
Upvotes: 1
Views: 215
Reputation: 350290
Here is a function that sets isExpanded
on the path to the item. The item itself (e.g. when it is has subitems) will not get isExpanded
set to true.
This function does also not clear the isExpanded
values that might have already been set to true
before calling the function.
const expandParentElements = (array, searchName) =>
array && array.some(item => item.name === searchName ||
expandParentElements(item.expandElements, searchName) && (item.isExpanded = true)
);
// Sample data from question
const elementsArray = [{name: 'test_1',isExpanded: false,expandElements: [{name: 'test_1_1',isExpanded: false,expandElements: [{name: 'test_1_1_1'},{name: 'test_1_1_2'}]},{name: 'test_1_2',isExpanded: false,expandElements: [{name: 'test_1_2_1'},{name: 'test_1_2_2'}]}]},{name: 'test_2',isExpanded: false,expandElements: [{name: 'test_2_1',isExpanded: false,expandElements: [{name: 'test_2_1_1'},{name: 'test_2_1_2'}]},{name: 'test_2_2',isExpanded: false,expandElements: [{name: 'test_2_2_1'},{name: 'test_2_2_2'}]}]}];
expandParentElements(elementsArray, "test_2_2_1");
console.log(elementsArray);
You may want to also use a function to collapse all, i.e. set all isExpanded
to false
:
const collapseAll = (array) =>
array.filter(item => item.expandElements)
.forEach(item => (item.isExpanded = false, collapseAll(item.expandElements)));
Upvotes: 2
Reputation: 313
elementsArray.forEach(element => {
let updateParent = element.expandElements.reduce(((prevFound, expandElement) => {
let found = expandElement.expandElements.some(obj => obj.name === "test_1_1_1")
expandElement.isExpanded = found
return prevFound || found
}), false)
element.isExpanded = updateParent
})
Upvotes: 0