1

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.

3
  • Any error in console ? Commented Sep 19, 2016 at 11:02
  • Try to represent your intent with a draw. Commented Sep 19, 2016 at 11:27
  • i.imgur.com/h4jML9e.png everything is button here, while order button is active it should display hidden elements Commented Sep 19, 2016 at 11:56

5 Answers 5

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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.

Comments

0

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) ; 
 }

})

Comments

0

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;
    };

});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.