Search code examples
javascriptrecursionlodash

Recursive function to build breadcrumbs from json menu object


So I've been struggling to wrap my head around this recursive function and get the right results.

const _ = require('lodash');

let config = {
    "Main": {
        children: {
            "Dashboard": "main.dashboard",
            "Account": {
                children: {
                    "Settings": "main.account.settings"
                }
            }
        }
    },
    "Statistics": {
        children: {
            "Test One": "main.statistics.test.one",
            "Test Two": "main.statistics.test.two"
        }
    }
}

let processNav = (config, parent) => {
    let children;
    let results = {};

    _.forOwn(config, (value, title) => {
        var breadcrumb = parent || title;

        if (value.children) {
            children = processNav(value.children, breadcrumb);
            _.assign(results, children);
        } else {
            results[value] = [breadcrumb, title];
        }
    });

    return results;
};

let breadcrumbs = processNav(config);

console.log(breadcrumbs);

// output
{ 'main.dashboard': [ 'Main', 'Dashboard' ],
  'main.account.settings': [ 'Main', 'Settings' ],
  'main.statistics.test.two': [ 'Statistics', 'Test Two' ] }

The output I'm looking for is more like this...

// expected output
{ 'main.dashboard': [ 'Main', 'Dashboard' ],
  'main.account.settings': [ 'Main', 'Account', 'Settings' ],
  'main.statistics.test.one': [ 'Statistics', 'Test One' ],
  'main.statistics.test.two': [ 'Statistics', 'Test Two' ] }

Can anyone help me wrap my head around this before I go crazy?


Solution

  • This approach doesn't use .lodash, just plain JS.

    let config = {    "Main": {        children: {            "Dashboard": "main.dashboard",            "Account": {                children: {                    "Settings": "main.account.settings"                }            }        }    },    "Statistics": {        children: {            "Test One": "main.statistics.test.one",            "Test Two": "main.statistics.test.two"        }    }};
    
    function loop(obj, path, breadcrumbs) {
      Object.keys(obj).forEach(k => {        
        if (obj[k].children) loop(obj[k].children, [...path, k], breadcrumbs);
        else breadcrumbs[obj[k]] = [...path, k];    
      });
    }
    
    let breadcrumbs  = {};
    loop(config, [], breadcrumbs);
    
    console.log(JSON.stringify(breadcrumbs, null, 2));
    .as-console-wrapper { max-height: 100% !important; top: 0; }