8

I need to create a dynamic nested ul\li list from json array.

NOTE! I can do that transformation my self using jQuery, but in this case i need to work with a string, since it's node.js and i don't have access to DOM.

Also the array can have different depth.

This is json data i work with and how it should look after transformation.

var data = [{"id": "1", "name": "name_1", "parent_id": "0", "depth": "0"},
        {"id": "2", "name": "name_2", "parent_id": "0", "depth": "0"},
        {"id": "3", "name": "name_3", "parent_id": "1", "depth": "1"},
        {"id": "4", "name": "name_4", "parent_id": "3", "depth": "2"}];

<ul>
  <li>name_1</li> //depth 0
  <li>name_2  //depth 0
    <ul>
      <li>name_3 //depth 1
        <ul>
          <li>name_3</li> //depth 2
        </ul>
      </li>
    </ul>
  </li>
</ul>

I hope this is clear. If not please ask any questions in the comment. Thank you in advanced.

Yaroslav Basovskyy
  • 702
  • 2
  • 6
  • 19
  • That's some weird JSON there. The whole point of JSON is, I think, the fact that it's hierarchical. Your JSON seems 'flattened'. – Kerstomaat Jan 15 '14 at 14:38
  • Yes, it is. So, i need to work with this ( – Yaroslav Basovskyy Jan 15 '14 at 14:44
  • That's some weird HTML to, if you at least put the next depth in it's own LI and not within the same LI as the previous depth, it would be easier. – adeneo Jan 15 '14 at 14:45
  • I agree with @simonplus - are you in control of the JSON format? If so, get rid of the ids and embed the children into an array attribute of their parents. Has the side effect that it'll be much smaller. – virtualnobi Jan 15 '14 at 14:53
  • You can see that each json line has a parent_id which match the id of one of the json strings. If you see another structure, please share. Thanks. – Yaroslav Basovskyy Jan 15 '14 at 14:54
  • I'm in node.js and mongodb. This json is being returned from db and has this structure. I can't do anything about it. – Yaroslav Basovskyy Jan 15 '14 at 14:56
  • If you can't change the format, tell us more about it: Is it guaranteed that all children of a node follow it immediately (including some grandchildren, if they exist)? For a robust solution which handles out-of-order cases, you'll need to convert the flat JSON format into a hierarchical one, from which you can generate
      s.
    – virtualnobi Jan 15 '14 at 15:07
  • Well, looking at the example data closely, node 3 is child of node 1, contrary to your
      s.
    – virtualnobi Jan 15 '14 at 15:11

3 Answers3

12

Try this:

var data = [{"id": "1", "name": "name_1", "parent_id": "0", "depth": "0"},
    {"id": "2", "name": "name_2", "parent_id": "0", "depth": "0"},
    {"id": "3", "name": "name_3", "parent_id": "1", "depth": "1"},
    {"id": "4", "name": "name_4", "parent_id": "3", "depth": "2"}];

var initLevel = 0;

var endMenu =getMenu("0");

function getMenu( parentID ){
       return data.filter(function(node){ return ( node.parent_id === parentID ) ; }).map(function(node){
           var exists = data.some(function(childNode){  return childNode.parent_id === node.id; });
           var subMenu = (exists) ? '<ul>'+ getMenu(node.id).join('') + '</ul>' : "";
           return '<li>'+node.name +  subMenu + '</li>' ;
       });
 }
console.log( '<ul>'+endMenu.join('')+ '</ul>');

However, I think the correct output based on your data will be something like:

    <ul>
        <li>name_1
            <ul>
                <li>name_3
                    <ul>
                        <li>name_4</li>
                    </ul>
                </li>
            </ul>
        </li>
        <li>name_2</li>
    </ul>

Here is the JSFiddle sample

Updated Version:

http://jsfiddle.net/LqES7/47/

Dalorzo
  • 19,834
  • 7
  • 55
  • 102
  • Hello again. After a little playing with this i found that it has a bug. Try to change third line parent_id to 2 and it's not working(( If you have any thoughts, please help. – Yaroslav Basovskyy Jan 17 '14 at 09:36
  • @user2960708 found it, I updated both the fiddle and the answer – Dalorzo Jan 17 '14 at 12:46
  • Yes, now it's working. Thank you. But i have one more challenge. I'm building sortable nested menu. And when i'm changing the order of element it isn't changing in db. So, i've added index value to each element and now i need to change the function to sort elements according to that index. It would be grate if you have any thoughts )) – Yaroslav Basovskyy Jan 17 '14 at 14:44
  • yes, i just getting the index of li according to it siblings and saving it to db. It looks like this now {"id": "1", "name": "name_1", "parent_id": "0", "depth": "0", index: 0} – Yaroslav Basovskyy Jan 17 '14 at 14:53
  • I am having problem with this example. Please check this fiddle http://jsfiddle.net/LqES7/16/ and tell me why it's getting the extra "," between two same level li tag – Monzurul Haque Aug 12 '14 at 16:52
  • @MonzurulHaque there is `.join()` missing in the inner getMenu this version: http://jsfiddle.net/LqES7/47/ – Dalorzo Aug 12 '14 at 19:32
1

I'd first convert the flat data to hierarchical json, using something like this, so it's more iterable. Then recursively iterate the JSON and add every element to a string.

Community
  • 1
  • 1
Kerstomaat
  • 673
  • 4
  • 13
0

If i understand the question correctly you are trying to genereat a list in html from a array of objects.

So if your not using JQuery, probably one of these will help you out:

And if your using JQuery, probably this will help you out:

Community
  • 1
  • 1
Erex
  • 1,625
  • 1
  • 17
  • 21