Join the Stack Overflow Community
Stack Overflow is a community of 6.8 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I am trying to loop through an array from JSON and display the contents more like a side menu. I wrote something like

<ul ng-repeat="(key, value) in menuList.Menu">
  <li>{{key}}</li>
  <ul ng-repeat="(key, value) in value">
    <li> {{key}}</li>  //second key
    <ul ng-repeat="(key, value) in value">
      <li> {{key}}</li> 
      <ul ng-repeat="(key, value) in value">
        <li> {{key}} : {{value}}</li>  
      </ul>
    </ul>
  </ul>
</ul>

The problem is my second key has both object and array. How do I display the value of Object and loop/ng-repeat just through the array. I cannot modify it with this as it will display the entire content of the array.

 <li> {{key}} : {{value}}</li>  

A part of my JSON for better understanding is given below:

{
  "class": 99,
  "mode" : 0,
  "Menu": [{
      "MenuNum":  1,
      "MenuItems":  [{
          "ItemNum":  0,
          "ItemDesc": "Main Menu",
          "ActionCode": "-",
          "ActionInst": ""
        } , {
          "ItemNum":  1,
          "ItemDesc": "BBQ",
          "ActionCode": "M",
          "ActionInst": "0992"
        }, {
          "ItemNum":  2,
          "ItemDesc": "Beverages",
          "ActionCode": "M",
          "ActionInst": "0992"
        }]
        },{
      "MenuNum":  2,
      "MenuItems":  [{
          "ItemNum":  0,
          "ItemDesc": "Sub Menu",
          "ActionCode": "-",
          "ActionInst": ""
        }, {
          "ItemNum":  1,
          "ItemDesc": "BBQTYPE1",
          "ActionCode": "P",
          "ActionInst": "0996"
        }, {
          "ItemNum":  2,
          "ItemDesc": "BeveragesTYPE1",
          "ActionCode": "P",
          "ActionInst": "0998"
      }]
  }]
}

I want the sidebar more like

THIS

share|improve this question
    
Can you please provide some sample data. – Shashank Agrawal Jan 1 '15 at 10:32
    
Also the DOM structure you expected from your sample data. – Shashank Agrawal Jan 1 '15 at 10:33
1  
I am not sure if I understand your question. It seems like ngSwitch is what you need. Set ngSwitch to check if the last second key is of Object type. If true, insert the DOM designed for the case of Object. Otherwise, insert the DOM designed for the case of Array. – tamakisquare Jan 1 '15 at 11:05
    
Can you give the HTML output you want? It isn't clear from the image what you're looking to produce. – benjaminjosephw Jan 1 '15 at 15:04
    
the menu should expand and collapse onclick.Here I have expended Menu. Then the 2nd object in it and then the first array in it. I dont think there is a better way to put it. And i cannot follow most of the answers below as my JSON is not as small as this example JSON. it have about 200 menus and each menu have about 10 to 40 menuItems. – RBz Jan 2 '15 at 4:08
up vote 1 down vote accepted

Presuming at the moment that you just want the ng-repeat logic, this may be what you are looking for:

  <ul ng-repeat="topMenu in menuList.Menu">
        <li>
            {{$index}}
        <ul>
            <li>
                MenuNum: {{topMenu.MenuNum}}
            </li>
            <li> MenuItems
                <ul ng-repeat="submenu1 in topMenu.MenuItems">
                    <li>
                        {{$index}}
                        <ul>
                            <li>ItemNum: {{submenu1.ItemNum}}</li>
                            <li>ItemDesc: {{submenu1.ItemDesc}}</li>
                            <li>ActionCode: {{submenu1.ActionCode}}</li>
                            <li>ActionInst: {{submenu1.ActionInst}}</li>
                          </ul>
                      </li>
                </ul>
            </li>
            </ul>
        </li>
    </ul>

If you then want a relatively easy way to do the menu opening/closing, you would probably want to put all this into an Angular accordion. I can probably help you with that if you want.

share|improve this answer
    
This works well. Is this the best way to go about this if I my JSON have 100's of menus and 10 to 50 menuItems? Also i want menu opening and closing. It will be great if you could help me with Angular accordion. – RBz Jan 2 '15 at 4:30
    
100's of menus sounds way too complex. It would be impossible to maintain and would probably overload the DOM to breaking point. Surely you can split up your material into different pages/modules dealing with different subjects. Or to make it maintainable and to keep your sanity you would have to simplify the structure into a form that lends itself to automation/parsing down a tree. – mwarren Jan 2 '15 at 8:33
    
You probably need something like Angular Treeview. I wouldn't try reinventing the wheel with something as complex as this. – mwarren Jan 2 '15 at 8:42
    
One last thing. Lets assume i have only one or two menus. Here in the code where i am getting {{submenu1.ActionInst}},I need to implement a logic which needs me to do another <ul ng-repeat="submenu1 in topMenu.MenuItems"> But I only need to get the submenu's for MenuItems which equals to submenu1.ActionInst.substring(3). Then I want the normal looping to continue. Is it possible to achieve? – RBz Jan 2 '15 at 9:33
    
I'm sure it's possible, but I don't quite understand what you are asking. Are you saying that the structure remains the same, but in some cases you don't want to see the submenu1 stuff unless something equals submenu1.ActionInst.substring(3)? Or are you saying that you will need a further submenu under submenu1 if submenu1.ActionInst.substring(3) equals something? – mwarren Jan 2 '15 at 10:19

It looks like you're trying to create a list with nested children. How about a recursive pattern which uses ng-include recursively to display all the nested children? Something like this:

<script type="text/ng-template" id="menuTree">
  {{ menuItem.name }}
  <ul ng-if="menuItem.children">
    <li ng-repeat="menuItem in menuItem.children" ng-include="'menuTree'"></li>
  </ul>
</script>

<ul>
  <li ng-repeat="menuItem in menuItems" ng-include="'menuTree'"></li>
</ul> 

I'm using a slightly different data structure to your code, but you should get the idea. Here's a demo: http://jsfiddle.net/mmmxh8kq/

EDIT:

If the data is as simple as the JSON you posted and you don't need a recursive menu, you could just try this:

<ul>
  <li ng-repeat="menus in menuList.Menu">
    {{ menus.MenuNum }}
    <ul>
      <li ng-repeat="menuItems in menus.MenuItems">
        {{ menuItems.ItemDesc }}
      </li>
    </ul>
  </li>
</ul>  

Demo: http://jsfiddle.net/n4mo80od/

share|improve this answer
    
I have added the JSON. I believe this solution is not for my kind of JSON data structure. – RBz Jan 1 '15 at 13:03
    
my JSON is not as small as this example JSON. it have about 200 menus and each menu have about 10 to 40 menuItems. I see below answer is one way to go about it.But the code may get a bit long. But I really didnt got how ng-include may be better. I understand it is something we use inside a view to avoid repeating ourself, in the cases where several views need the same code included. But how is it better than the below mentioned answer? – RBz Jan 2 '15 at 4:26
    
The ng-include method is for recursive menus. Say you had a menu which had sub-menu, and that sub-menu had it's own sub-menus - you'd want a way to handle this without repeating yourself too much. If you know that's not the case, a simple ng-repeat will do. – benjaminjosephw Jan 2 '15 at 10:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.