Andrew
Andrew

Reputation: 111

Find element inside tree and change it's parents' properties values

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:

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

Answers (2)

trincot
trincot

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

Sumith
Sumith

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

Related Questions