CountGradsky
CountGradsky

Reputation: 268

ng-repeat based on <select> option

Since I expanded my project I stumbled on a problem. This is my main object:

{
  screens: [{
    id: 0,
    name: 'Screen0',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }, {
    id: 1,
    name: 'Screen1',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }, {
    id: 2,
    name: 'Screen2',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }]
};

The problem lays in the select tag which is being populated this way:

<select ng-model="ScreenService.config.screenConfig.current">
    <option 
    value="{{screen.id}}" 
    ng-repeat="screen in ConfiguratorService.screens">
     {{screen.name}}
    </option>
</select>

In a separate container, but in the same controller, I am repeating sections within the screens. So I cannot do something like

ng-repeat = "screens in ConfiguratorService.screens"
ng-repeat = "sections in screens"
ng-repeat = "sectionItems in sections"

I need to repeat the sections based on the value of selected screen in dropdown. I would like to avoid repeating them all and hiding them since they are heavily populated, but it might be a last resort.

Edit: Sections and sectionItems will be repeated as ul-li

Upvotes: 1

Views: 14377

Answers (4)

S. Divya
S. Divya

Reputation: 91

Check whether if this works for you....

The Second select value will appear based on first selected Id. So the Second select dropdown value will come only after you select the first select dropdown.

 <html>
<head>
  <title>Angular JS Controller</title>
  <script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body>
  <div ng-app = "mainApp" ng-controller = "studentController">
     <select ng-model="current" ng-change="captureChange(current)" ng-options="option.id as option.name for option in screens">
     </select>
     <select ng-model="current123" ng-options="item.id as item.name for item in Collectval" ng-change="captureItemChange(current123)">
     </select>
  </div>

  <script>
     var mainApp = angular.module("mainApp", []);
     mainApp.controller('studentController', function($scope) {
      $scope.screens= [{
                            id: 0,
                            name: 'Screen0',
                            sections: [{
                                id: 0,
                                sectionItems: [
                                {id:1, name:"Aarthi"},{id:2, name:"Roopa"}
                                ]
                            }, {
                                id: 1,
                                sectionItems: [
                                {id:3, name:"Chitra"},{id:4, name:"Prakash"}
                                ]
                            }, {
                                id: 2,
                                sectionItems: [
                                {id:5, name:"Lalitha"},{id:6, name:"Sekaran"}
                                ]
                            }]
                        }, {
                            id: 1,
                            name: 'Screen1',
                            sections: [{
                                id: 0,
                                sectionItems: [
                                {id:7, name:"Vijay"},{id:8, name:"Sethupathi"}
                                ]
                            }, {
                                id: 1,
                                sectionItems: [
                                {id:9, name:"Aravind"},{id:10, name:"Swamy"}
                                ]
                            }, {
                                id: 2,
                                sectionItems: [
                                {id:11, name:"Vinay"},{id:12, name:"Raja"}
                                ]
                            }]
                        }, {
                            id: 2,
                            name: 'Screen2',
                            sections: [{
                                id: 0,
                                sectionItems: [
                                {id:13, name:"Brian"},{id:14, name:"Laura"}
                                ]
                            }, {
                                id: 1,
                                sectionItems: [
                                {id:15, name:"Sachin"},{id:16, name:"Tendulkar"}
                                ]
                            }, {
                                id: 2,
                                sectionItems: [
                                {id:17, name:"Rahul"},{id:18, name:"Dravid"}
                                ]
                            }]
                        }]
                        $scope.Collectval=[];
                        $scope.captureChange = function(val){
                        angular.forEach($scope.screens,function(item){
                        if(item.id==val){
                        angular.forEach(item.sections, function(data){
                        angular.forEach(data.sectionItems, function(vval){
                        $scope.Collectval.push(vval);
                        })

                        })
                        }
                        })
                        };

                        console.log($scope.Collectval);
        $scope.captureItemChange = function(value){
        //alert(value);
        }                

     });
  </script>

Upvotes: 1

Kyle
Kyle

Reputation: 5557

This is how you do it using three select dropdowns: https://jsfiddle.net/u037x1dj/1/

Definitely messy using multiple nested <optgroup>. I would re-think what you're trying to do and re-design the UI. But this is how you do it:

<select ng-model="myModel">
    <optgroup label="screen_{{screen.id}}" ng-repeat="screen in screens">
        <optgroup label="section_{{section.id}}" ng-repeat="section in screen.sections">
            <option ng-repeat="sectionItem in section.sectionItems" value="sectionItem.id">{{sectionItem.name}}</option>
        </optgroup>
    </optgroup>
</select>

EDIT: I would have three separate dropdowns, the subsequent dropdowns would filter on what is selected before it. Use ng-disabled to disable dropdowns if there first one hasn't been selected yet.

Screen:

<select ng-model="selectedScreen" ng-options="screen as screen.name for screen in screens">
</select>

Section:

<select ng-disabled="selectedScreen === null" ng-model="selectedSection" ng-options="section as section.name for section in screens.sections | filter: selectedScreen">
</select>

Section Items:

<select ng-disabled="selectedSection === null" ng-model="selectedSectionItem" ng-options="item as item.name for item in screens.sections.sectionItems | filter: selectedSection">
</select>

Upvotes: 0

Renan Ferreira
Renan Ferreira

Reputation: 2150

If I understood right, I think you are looking for something like this. You need to hook an ng-change in the select tag, find the object related to the ID selected, and just than, create you second ng-repeat.

This is an example:

https://jsfiddle.net/relferreira/ja776cej/

HTML:

<div data-ng-app="app">

  <div data-ng-controller="MainController as mainVm">
    <select data-ng-model="mainVm.selectedScreenIndex" data-ng-change="mainVm.select()">
      <option 
      value="{{screen.id}}" 
      ng-repeat="screen in mainVm.screens">
       {{screen.name}}
      </option>
  </select>
  <ul>
    <li data-ng-repeat="sectionItems in mainVm.selectedItem.sections">{{sectionItems}}</li>
  </ul>
  </div>

</div>

JS:

angular.module('app', []);

angular.module('app')
    .controller('MainController', mainController);

mainController.$inject = ['$scope'];

function mainController($scope){

    var vm = this;
  vm.select = select;
  vm.selectedScreen = null;
  vm.selectedScreenIndex = null;
  vm.screens =  [{
    id: 0,
    name: 'Screen0',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }, {
    id: 1,
    name: 'Screen1',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }, {
    id: 2,
    name: 'Screen2',
    sections: [{
      id: 0,
      sectionItems: []
    }, {
      id: 1,
      sectionItems: []
    }, {
      id: 2,
      sectionItems: []
    }]
  }];

  function select(){
    vm.screens.forEach(function(item){
        if(item.id == vm.selectedScreenIndex){
        vm.selectedItem = item;
      }
    });
  }

}

Upvotes: 2

Qianyue
Qianyue

Reputation: 1777

Save your selected screen in a variable (by ng-model):

<select ng-model="selectedId">
  <option 
    value="{{screen.id}}" 
    ng-repeat="screen in ConfiguratorService.screens">
    {{screen.name}}
  </option>
</select>

In that seperate container, set the vm with ConfiguratorService.screens[selectedId].

For the original ng-model(ScreenService.config.screenConfig.current), it can be set by ScreenService.config.screenConfig.current = selectedId.

Upvotes: 5

Related Questions