bashante
bashante

Reputation: 23

Array in array, angularJS, ng-repeat

im struggling with iterating over arrays in arrays. I need to create buttonlike vertical menu and cant get it work.

angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {

    $scope.items = [
        'Home',
        'Orders':
        {
            orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']
        },
        'Users',
        'Resources',
        'Settings',
        'Help'
    ];
    $scope.activeMenu = $scope.items[0];
    $scope.setActive = function(item) {
      $scope.activeMenu = item;
    };

});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
   <div class="col-md-3">
       <div ng-controller="NavigationController">
           <input type="text" placeholder="Search" ng-model="filterQuery" />
           <ul class="list-group">
               <li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery"><a href="#">{{ item }}</a>
               </li>
           </ul>
       </div>
   </div>
    <script src="js/MainController.js"></script>
</body>
</html>

What i need to do is display array of items and while Orders item is active expand it with elements given in other array. To be honest i just dont know how to make it.

Upvotes: 1

Views: 1384

Answers (5)

ngCoder
ngCoder

Reputation: 2105

I believe there are so many ways to answer this question,although I've made a sample plunker for your problem.Below is how your

HTML will look like

<body ng-app="NavigationApp">
    <div class="col-md-3">
        <div ng-controller="NavigationController">
            <input type="text" placeholder="Search" ng-model="filterQuery" />
            <ul class="list-group">
                <li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">
                    <a href="#">
                        <p ng-hide="item.dropdown"> {{ item.name }}</p>
                        <p ng-show="item.dropdown" ng-repeat="values in item.dropdown"> {{ values }}</p>
                    </a>
                </li>
            </ul>
        </div>
    </div>

</body>

JS look like

angular.module('NavigationApp', []).controller('NavigationController', function($scope) {

    var orderItemsObj = {
        orders: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
    };
    $scope.items = [{
        name: 'Home'
    }, {
        name: 'Orders',
        dropdown: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
    }, {
        name: 'Users'
    }, ];

    $scope.activeMenu = $scope.items[0];
    $scope.setActive = function(item) {
        $scope.activeMenu = item;
    };

});

Upvotes: 0

Amr Ibrahim
Amr Ibrahim

Reputation: 2234

this filter work correctly

INPUT :

['Home',{ 'Orders':{orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']}},'Users','Resources','Settings','Help']

OUTPUT :

 ["Home", "Orders", "Open", "Closed", "New", "Forgotten", "Users", "Resources", "Settings", "Help"]

app.filter('customfilter', function () {
return function (data) {          
    function clean(item)
    {
      var result = [] ;
      // check if type is array
      if(Array.isArray(item)){
        // parse array
        item.forEach(function(i){
          result = result.concat(clean(i));
        })
      }// check if type is opject
      else if(typeof item =="object"){
          // parse opject
          Object.keys(item).map(function (key) {
             result = result.concat(clean(item[key]));
          });
      }else{
        result= [item]
      }
      return result ;
     } 
   return clean(data) ; 
 }

})

Upvotes: 0

bashante
bashante

Reputation: 23

angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {

    $scope.items = {
        main:['Home','Orders','Users','Resources','Settings','Help'],
        sub:['Open','Closed','New','Forgotten']
    };
    $scope.activeMenu = $scope.items[0];
    $scope.setActive = function(item) {
      $scope.activeMenu = item;
    };

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
   <div class="col-md-3">
       <div ng-controller="NavigationController">
           <input type="text" placeholder="Search" ng-model="filterQuery" />
           <ul class="list-group">
               <li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items.main | filter:filterQuery"><a href="#">{{ item }}</a>
                    <ul>
                        <li class="btn btn-lg list-group-item" ng-repeat="it in items.sub" ng-if="activeMenu === 'Orders'">{{it}}</li>
                    </ul>
               </li>
           </ul>
       </div>
   </div>
    <script src="js/MainController.js"></script>
</body>
</html>

This is closer to what i want to achieve. But i dont know how to apply this nested UL to only one Li from parent list.

Upvotes: 0

Chris Satchell
Chris Satchell

Reputation: 749

Here's a quick, basic example of what you could use:

$scope.items = [{
    name: 'Home'
}, {
    name: 'Orders',
    dropdown: [{
        name: 'Orders'
    }]
},{
    name: 'Users'
},
...
];
<li ng-repeat="item in items | filter:filterQuery" class="btn btn-lg list-group-item dropdown" ng-class="{active: activeMenu === item}" ng-click="setActive(item)">
    <a aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" class="dropdown-toggle" href="#">
        {{ item.name }} <span class="caret" ng-if="item.dropdown"></span>
    </a>
    <ul ng-if="item.dropdown" class="dropdown-menu">
        <li ng-repeat="dItem in item.dropdown">
            <a href="#">{{dItem.name}}</a>
        </li>
    </ul>
</li>

I'd suggest having another indepth look at https://docs.angularjs.org/api/ng/directive/ngRepeat to fully understand the structure required by the directive.

Upvotes: 0

nikjohn
nikjohn

Reputation: 21910

You are trying to ng-repeat over a heterogeneus array. i.e. it's elements are not all of the same type. The implementation logic needs to change here.

One thing you can do if your data structure is not flexible, is to use a typeof item === 'object' to filter out the object from the strings, or conversely check for typeof string

Upvotes: 1

Related Questions