Fer Vargas Fer Vargas - 3 months ago 7
AngularJS Question

AngularJS - Multiple Dropdowns

I'm currently working on a project where I have a button that adds a dropdown everytime you click on the button.

Clicking the button not only shows the dropdown, but also a "Remove item" button, where you can remove the respective item added.

Then if you select an option from the dropdown, it will show another dropdown with more options, depending on what you chose on the first dropdown.

You can choose from the dropdown two options, movies or games.

And then on the second dropdown should appear a movie list or a game list depending on what you selected.

You can see HERE the current fiddle.

index.html:

<div ng-app="myApp" ng-controller="testCtrl">
<button ng-click = "addNewItem()">Add new Item</button>

<div ng-repeat="item in itemSet.item track by $index">
<button ng-click = "removeItem($index)">Remove item</button>

<select ng-model="category"
ng-change="changeCategory(category)"
ng-options="category as category for category in categoryTypes">
<option></option>
</select>

<select ng-show="movieSelected"
ng-model="movieType"
ng-options="movie as movie for movie in movieCategories">
<option></option>
</select>

<select ng-show="gameSelected"
ng-model="gameType"
ng-options="game as game for game in gameCategories">
<option></option>
</select>
</div>
</div>


app.js:

var myApp = angular.module('myApp', []);

myApp.controller('testCtrl', ['$scope', function ($scope) {
$scope.categoryTypes = ['Movies', 'Games'];

$scope.gameCategories = ['RPG', 'Sports'];
$scope.movieCategories = ['Action', 'SciFi'];

$scope.itemSet = { item : [] };
$scope.itemSet.item = [];

$scope.gameSelected = false;
$scope.movieSelected = false;

$scope.addNewItem = function () {
$scope.itemSet.item.push('');
};

$scope.removeItem = function (index) {
$scope.itemSet.item.splice(index, 1);
};

$scope.changeCategory = function(category) {
if(category == 'Movies') {
$scope.gameSelected = false;
$scope.movieSelected = true;
} else {
$scope.gameSelected = true;
$scope.movieSelected = false;
}
};
}]);


There are some things that are going wrong with this. With no order in particular:

For example, if I added 3 items, and then want to delete the first one, it will delete the third, then the second and finally the first if you keep pressing the "Remove Item" button.

If I add 3 items and I select "movies" from the first dropdown on the first row for example, it will display all of the other dropdowns with the possibility of choosing the items from the movie list on all of them, even if I didn't choose anything from the other rows.

Also if you want to add, lets say, 2 items, in one item you pick first "movies" and then on the second one you pick "games", the "extra" dropdowns will show the list of games instead of the respective list of items for each of the cases.

The actual project works similar to this, but with 4 dropdowns, and the information comes from a database but I guess that with the Fiddle should be enough to get the idea and to take a possible solution to the actual project.

If someone could help me out on this one I'll be very gratefull!

Answer

Your code has a big problem that is: you have the same ngModel for all items in ngRepeat.

After fixing this, you can simplify a lot your code.

You don't need to use ngChange to know what category is selected, you can simply use ngSwitch directive what fits well in this case.

See it working:

(function() {
  'use strict';

  angular
    .module('myApp', [])
    .controller('testCtrl', testCtrl);

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

  function testCtrl($scope) {
    $scope.categoryTypes = ['Movies', 'Games'];

    $scope.gameCategories = ['RPG', 'Sports'];
    $scope.movieCategories = ['Action', 'SciFi'];

    $scope.itemSet = {
      item: []
    };

    $scope.addNewItem = function() {
      $scope.itemSet.item.push({});
    };

    $scope.removeItem = function(index) {
      $scope.itemSet.item.splice(index, 1);
    };
  }
})();
<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>

<body>
  <div ng-app="myApp" ng-controller="testCtrl">
    <button ng-click="addNewItem()">Add new Item</button>
    <div ng-repeat="item in itemSet.item track by $index">
      <button ng-click="removeItem($index)">Remove item</button>
      <select ng-model="item.category"
              ng-options="category for category in categoryTypes">
        <option value hidden>Select a category</option>
      </select>
      <span ng-switch="item.category">
        <select ng-switch-when="Movies"
                ng-model="item.movie"
                ng-options="movie for movie in movieCategories">
         <option value hidden>Select a movie</option>  
        </select>
        <select ng-switch-when="Games"
                ng-model="item.game"
                ng-options="game for game in gameCategories">
         <option value hidden>Select a game</option>  
        </select>
      </span>
    </div>
    <pre ng-bind="itemSet.item | json"></pre>
  </div>
</body>

</html>

Comments