the_haystacker
the_haystacker

Reputation: 1625

Javascript - Create parent-child navigation from json

I'm trying to create navigation from json using parent child relation. My json looks like this.

Somehow I'm getting maximum callstack exceeded error message while printing the navigation

 [
  {
    "__type": "Service+Menu",
    "ID": 1,
    "Caption": "Master",
    "URL": "",
    "Description": "Main menu",
    "ParentID": ""
  },
  {
    "__type": "Service+Menu",
    "ID": 2,
    "Caption": "Branch Details",
    "URL": "~/UI/Masters/Branch_Details.aspx",
    "Description": "Branch Details",
    "ParentID": "1"
  },
  {
    "__type": "Service+Menu",
    "ID": 123,
    "Caption": "Bank Details",
    "URL": "",
    "Description": "Bank Details",
    "ParentID": "1"
  },
  {
    "__type": "Service+Menu",
    "ID": 124,
    "Caption": "Bank Details Entry",
    "URL": "~/UI/Loans/BankEntryRectification.aspx",
    "Description": "Bank Details Entry",
    "ParentID": "123"
  },
  {
    "__type": "Service+Menu",
    "ID": 10,
    "Caption": "Loans&Printing",
    "URL": "",
    "Description": "",
    "ParentID": ""
  },
  {
    "__type": "Service+Menu",
    "ID": 11,
    "Caption": "Loan Form Request",
    "URL": "~/UI/Masters/LoanFormRequest.aspx?Type=General",
    "Description": "Loan Form Request",
    "ParentID": "10"
  }
]

I wrote a recursive function to loop through it, but somehow I'm getting maximum call stack exceeded error. The code I'm using is :

console.log(buildNavigation(data));

function buildNavigation(items, parent = '') {
  var next = function (items, parent) {
    return items.filter(function (item) {
      return (item.ParentID == parent);
    })
  }

  var output = '<ul>';

  for (var key in next(items, parent)) {
    output += '<li>';
    output += '<a href="#">' + items[key].Caption + '</a>';

    if (next(items, items[key].ID)) {
      output += buildNavigation(next(items, items[key].ID), parent);
    }

    output += '</li>';
  }

  output += '</ul>';

  return output;
}

Any Idea where I'm making the mistake?

Upvotes: 0

Views: 739

Answers (1)

sam
sam

Reputation: 1807

Based on your code, I wrote a working version. Please run the code snippet, and click the "Build Navigation" button to see if this is want you want.

var data = [
  {
    "__type": "Service+Menu",
    "ID": 1,
    "Caption": "Master",
    "URL": "",
    "Description": "Main menu",
    "ParentID": ""
  },
  {
    "__type": "Service+Menu",
    "ID": 2,
    "Caption": "Branch Details",
    "URL": "~/UI/Masters/Branch_Details.aspx",
    "Description": "Branch Details",
    "ParentID": "1"
  },
  {
    "__type": "Service+Menu",
    "ID": 123,
    "Caption": "Bank Details",
    "URL": "",
    "Description": "Bank Details",
    "ParentID": "1"
  },
  {
    "__type": "Service+Menu",
    "ID": 124,
    "Caption": "Bank Details Entry",
    "URL": "~/UI/Loans/BankEntryRectification.aspx",
    "Description": "Bank Details Entry",
    "ParentID": "123"
  },
  {
    "__type": "Service+Menu",
    "ID": 10,
    "Caption": "Loans&Printing",
    "URL": "",
    "Description": "",
    "ParentID": ""
  },
  {
    "__type": "Service+Menu",
    "ID": 11,
    "Caption": "Loan Form Request",
    "URL": "~/UI/Masters/LoanFormRequest.aspx?Type=General",
    "Description": "Loan Form Request",
    "ParentID": "10"
  }
]

function buildNavigation(items, parent = '') {
  var next = function (items, parent) {
    return items.filter(function (item) {
      return (item.ParentID == parent);
    })
  }

  var output = '<ul>';
  
  var subItems = next(items, parent)
  for (var key in subItems) {
    output += '<li>';
    output += '<a href="#">' + subItems[key].Caption + '</a>';
    var subItems2 = next(items, subItems[key].ID)
    if (subItems2) {
      output += buildNavigation(items, subItems[key].ID);
    }

    output += '</li>';
  }

  output += '</ul>';

  return output;
}

document.querySelector('#build').onclick = function() {
  document.querySelector('#result').innerHTML = buildNavigation(data)
}
<button id="build">Build Navigation</button>
<div id="result"></div> 

Upvotes: 2

Related Questions