1

I have a nested array of objects. I would like to get an object that only provides me the onClick property as the key and the value as null. I am able to navigate to the first level, but I am unable to navigate down further. How do I go forward doing it?

const headers = [{
    id: 'title1',
    title: 'Title 1',
    children: [
        {
            title: 'Children 1',
            child: [
                {
                    title: 'Child 1',
                      id: 'child1Id',
                      onClick: 'child1Click',
                      url: '/child1'
                },
                {
                    title: 'Child 2',
                    id: 'child2Id',
                    onClick: 'child2Click'
                }
            ]
      },
      {
            title: 'Children 2',
            child: [
                {
                    title: 'Child 3',
                    id: 'child3Id',
                    onClick: 'child3Click',
                },
                {
                    title: 'Child 4',
                    id: 'child4Id',
                    onClick: 'child4Click'
                }
            ]
      }
    ]
  },
  {
    id: 'title2',
    title: 'Title 2',
    privilege: '',
    children: [{
        title: 'Children 3',
        privilege: '',
        child: [{
            title: 'Child 5',
            id: 'child5Id',
            onClick: 'child3Click',
            url: '/child5',
            privilege: ''
          },
          {
            title: 'Child 6',
            id: 'child6Id',
            onClick: 'child6Click',
            url: '/child6',
            privilege: ''
          }
        ]
      },
      {
        title: 'Children 4',
        privilege: '',
        child: [{
            title: 'Child 7',
            id: 'child7Id',
            onClick: 'child7Click',
            url: '/child7',
            privilege: ''
          },
          {
            title: 'Child 8',
            id: 'child8Id',
            onClick: 'child8Click',
            url: '/child8',
            privilege: ''
          }
        ]
      }
      ]
    }
];

const routesMap = ({ onClick, children }) => (onClick ? { [onClick]: null } : _.flatMap(children, routesMap));

const routeStates = _.assign({}, ..._.flatMap(headers, routesMap));

console.log(routeStates)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Expected Output:

  {
      child1Click: null,
      child2Click: null,
      child3Click: null,
      child4Click: null,
      child5Click: null,
      child6Click: null,
      child7Click: null,
      child8Click: null,
  }

Please advice. Any help is highly appreciated.

0

3 Answers 3

2

Using vanilla JS you can use 3 nested map loops to get the onClick values, and return a an object with the value as property. Use Array.flat() to convert to a single array, and spread into Object.assign() to get an object.

const fn = headers => Object.assign({}, ...headers
  .map(({ children }) => 
    children.map(({ child }) => child.map(({ onClick }) => ({ [onClick]: null })))
  ) // extract onClick values
  .flat(Infinity) // flatten to a single array
)

const headers = [{"id":"title1","title":"Title 1","children":[{"title":"Children 1","child":[{"title":"Child 1","id":"child1Id","onClick":"child1Click","url":"/child1"},{"title":"Child 2","id":"child2Id","onClick":"child2Click"}]},{"title":"Children 2","child":[{"title":"Child 3","id":"child3Id","onClick":"child3Click"},{"title":"Child 4","id":"child4Id","onClick":"child4Click"}]}]},{"id":"title2","title":"Title 2","privilege":"","children":[{"title":"Children 3","privilege":"","child":[{"title":"Child 5","id":"child5Id","onClick":"child3Click","url":"/child5","privilege":""},{"title":"Child 6","id":"child6Id","onClick":"child6Click","url":"/child6","privilege":""}]},{"title":"Children 4","privilege":"","child":[{"title":"Child 7","id":"child7Id","onClick":"child7Click","url":"/child7","privilege":""},{"title":"Child 8","id":"child8Id","onClick":"child8Click","url":"/child8","privilege":""}]}]}]

const routeStates = fn(headers)

console.log(routeStates)

With lodash you can use _.flatMapDeep() instead of Array.flat():

const fn = headers => Object.assign({}, ...
  _.flatMapDeep(headers, ({ children }) => 
    _.map(children, ({ child }) => _.map(child, ({ onClick }) => ({ [onClick]: null })))
  ) // extract onClick values and flatte
)

const headers = [{"id":"title1","title":"Title 1","children":[{"title":"Children 1","child":[{"title":"Child 1","id":"child1Id","onClick":"child1Click","url":"/child1"},{"title":"Child 2","id":"child2Id","onClick":"child2Click"}]},{"title":"Children 2","child":[{"title":"Child 3","id":"child3Id","onClick":"child3Click"},{"title":"Child 4","id":"child4Id","onClick":"child4Click"}]}]},{"id":"title2","title":"Title 2","privilege":"","children":[{"title":"Children 3","privilege":"","child":[{"title":"Child 5","id":"child5Id","onClick":"child3Click","url":"/child5","privilege":""},{"title":"Child 6","id":"child6Id","onClick":"child6Click","url":"/child6","privilege":""}]},{"title":"Children 4","privilege":"","child":[{"title":"Child 7","id":"child7Id","onClick":"child7Click","url":"/child7","privilege":""},{"title":"Child 8","id":"child8Id","onClick":"child8Click","url":"/child8","privilege":""}]}]}]

const routeStates = fn(headers)

console.log(routeStates)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

Can I just replace the functions to lodash or is there a more streamlined answer using lodash as like your answer in stackoverflow.com/a/58470901/6731368 ?
With lodash you can save a line by using _.flatMapDeep().
1

try to access it in a loop and to access it try this as it is an object...

for ( let i = 0; i < headers.length; i++ ) {

   for (let j = 0; j < headers[i].children.length; j++ ) {

     for (let k = 0; k < headers[i].children[j].child.length; j++ ) {

       console.log( headers[i].children[j].child[k].onClick);

    }

  }

}

it will print as follows ...

  child1Click,
  child2Click,
  child3Click,
  child4Click,
  child5Click,
  child6Click,
  child7Click,
  child8Click

if you want to set the all childClick to null try adding this..

console.log( headers[i].children[j].child[k].onClick: null);

i hope it helps

1 Comment

It should be noted that this will only work for this very specific data structure as provided by the example
1

I borrowed a solution I found here to create this:

var headers = [
    //...
];
var newObj = {};

function iterate(obj) {
    Object.keys(obj).forEach(key => {

    if (key === 'onClick') {
        newObj[obj[key]] = 'null';
    }

    if (typeof obj[key] === 'object') {
            iterate(obj[key])
        }
    })
}

iterate(headers);
console.log(newObj);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.