Last Updated: March 07, 2016
· horyd

Cascading selects in AngularJS

I just finished writing up an answer on SO to a users question: how do I implement cascading selects (where the options on each select is exclusive of what has already been selected)?

Here is the solution I came up with: http://jsfiddle.net/jarydcarolin/aLyzn30m/1/

Let's take a closer look at what's going on.

<div ng-repeat="result in resultArray track by $index">
var n = 3;
$scope.resultArray = [];
for (var i = 0; i < n; i++) {$scope.resultArray.push({})}

Ok so first we start by preparing the array in which we would like our choices to populate into. I've populated it with empty objects such that the values will bind correctly from the child scopes (of the ng-repeats) and the parent scope (which is where the options logic is occuring). I use track by $index so I don't get a dupes error from Angular.

<select ng-model="result.car" ng-options="o as o for o in carArray($index)"></select>
$scope.carArray = function (index) {
  var cars =  ['Renault', 'Holden', 'Ford','Dodge'];
  return cars.filter(function (el) {
    return ($scope.resultArray.map(function(e){return e.car}).slice(0,index).indexOf(el) === -1)

Given that every select element must show a different set of options I have implemented a function in the parent scope to accept the child scopes $index and return an array. Let's focus on the second select element (where index = 1): we look at the full array of cars and then filter it. We need to check if any of those car values exist in our resultsArray, but we're only interested in those array entries that are BEFORE the entry for our own index, which is why we use the slice method. If the car is not in that part of the resultArray then it's good to be selected at the given index :)

Hope that helps anyone. Post a comment if you would like clarification or (even better) have a niftier solution ;)