siamak siamak - 6 months ago 15
AngularJS Question

how to filter a combo box that is created by a Ng-Repeat based on the same combo box in the previous row in Angular js?

I have a select element that is repeated by a ng-repeat directive when the "Addbutton" clicked . the object that fills the select element has a format like this :

{ id: 1, Title: 'AAA', priority: 1 },


I want when user selects an option from this combo box and clicks on the "Addbutton",
in the next row only options that have priority greater than the previous selected item priority would be list and shown .

This is my code :

<!DOCTYPE html>
<html ng-app="mainApplication">
<head>
<title></title>

<meta charset="utf-8" />

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

<script>
var MainApplication = angular.module('mainApplication', []);
MainApplication.controller('mainController', ['$scope', function ($scope)
{
$scope.AddressPrefix = [
{ id: 1, Title: 'AAA', priority: 1 },
{ id: 1, Title: 'BBB', priority: 2 },
{ id: 1, Title: 'CCC', priority: 3 },
{ id: 1, Title: 'DDD', priority: 4 },
{ id: 1, Title: 'EEE', priority: 5 },
{ id: 1, Title: 'FFF', priority: 6 },
{ id: 1, Title: 'GGG', priority: 7 },
{ id: 1, Title: 'HHH', priority: 8 },
{ id: 1, Title: 'III', priority: 2 },
{ id: 1, Title: 'jjj', priority: 2 },
{ id: 1, Title: 'kkk', priority: 2 },
{ id: 1, Title: 'LLL', priority: 10 },
{ id: 1, Title: 'MMM', priority: 9 },
{ id: 1, Title: 'ooo', priority: 7 },
{ id: 1, Title: 'PPP', priority: 12 },
{ id: 1, Title: 'qqq', priority: 3 },
{ id: 1, Title: 'RRR', priority: 13 },
{ id: 1, Title: 'zzz', priority: 14 },

];

$scope.AddressControls = [{ id: 1 }];
$scope.btnAddressAdd_click = function () {
var newItemNo = $scope.AddressControls.length + 1
$scope.AddressControls.push({ 'id': newItemNo });
};
$scope.btnAddressRemove_click = function () {
var lastItem = $scope.AddressControls.length - 1
$scope.AddressControls.splice(lastItem);
};
}]);
</script>

</head>
<body dir="rtl" ng-controller="mainController">
<div class="row" >

<div class="col-sm-6">
<button type="button" id="btnAddressAdd" class="btn btn-primary" ng-click="btnAddressAdd_click()">
<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true" style="font-size:1.2em"></span>
</button>
<button type="button" id="btnAddressRemove" class="btn btn-danger" ng-click="btnAddressRemove_click()" ng-disabled="AddressControls.length==1">
<span class="glyphicon glyphicon-minus" aria-hidden="true" style="font-size:1.2em"></span>
</button>
</div>
</div>
<hr />

<fieldset class="row " id="Address" ng-repeat="item in AddressControls" ng-disabled="$first">

<div class="col-sm-1" >
<div class="form-group">
<label >
prefix
</label>
</div>
</div>
<div class="col-sm-3" >
<div class="form-group">
<span></span>
<select class="form-control" ng-model="prefixSelecteditem" ng-options="prefix.Title for prefix in AddressPrefix">
<option value="">--select option--</option>
</select>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<div class="errorBlock">
</div>
<input class="form-control" type="text" value="" style="height:32px">
</div>
</div>

</fieldset>

</body>
</html>


link of source code in codepen

Edit



I have some ideas how to to do it when "Addbutton" clicked but I am wondering how its possible to achieve this functionality when there are some active combo boxes and user selects or changes the option of one of them.

Answer

There is many approaches to achieve this. there is two:

Method 1: Using Angular Filter In HTML

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

MainApplication.controller('mainController', ['$scope', function($scope) {
  $scope.AddressPrefix = [{
    id: 1,
    Title: 'AAA',
    priority: 1
  }, {
    id: 1,
    Title: 'BBB',
    priority: 2
  }, {
    id: 1,
    Title: 'CCC',
    priority: 3
  }, {
    id: 1,
    Title: 'DDD',
    priority: 4
  }, {
    id: 1,
    Title: 'EEE',
    priority: 5
  }, {
    id: 1,
    Title: 'FFF',
    priority: 6
  }, {
    id: 1,
    Title: 'GGG',
    priority: 7
  }, {
    id: 1,
    Title: 'HHH',
    priority: 8
  }, {
    id: 1,
    Title: 'III',
    priority: 2
  }, {
    id: 1,
    Title: 'jjj',
    priority: 2
  }, {
    id: 1,
    Title: 'kkk',
    priority: 2
  }, {
    id: 1,
    Title: 'LLL',
    priority: 10
  }, {
    id: 1,
    Title: 'MMM',
    priority: 9
  }, {
    id: 1,
    Title: 'ooo',
    priority: 7
  }, {
    id: 1,
    Title: 'PPP',
    priority: 12
  }, {
    id: 1,
    Title: 'qqq',
    priority: 3
  }, {
    id: 1,
    Title: 'RRR',
    priority: 13
  }, {
    id: 1,
    Title: 'zzz',
    priority: 14
  }, ];

  $scope.AddressControls = [{
    id: 1
  }];
  $scope.btnAddressAdd_click = function() {
    var newItemNo = $scope.AddressControls.length + 1
    $scope.AddressControls.push({
      'id': newItemNo
    });
  };
  $scope.btnAddressRemove_click = function() {
    $scope.AddressControls.pop();
  };

  $scope.myFilter = function(index) {
    return function(option, optionIndex, allOptions) {
      var lastSelectedOption = (index > 0) && $scope.AddressControls[index - 1] && $scope.AddressControls[index - 1].prefixSelecteditem;
      if (!lastSelectedOption) return true;
      return option.priority > lastSelectedOption.priority;
    }
  }
}]);
<html ng-app="mainApplication">

<head>
  <title></title>

  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
</head>

<body dir="rtl" ng-controller="mainController">
  <div class="row">

    <div class="col-sm-6">
      <button type="button" id="btnAddressAdd" class="btn btn-primary" ng-click="btnAddressAdd_click()">
				<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true" style="font-size:1.2em"></span>
			</button>
      <button type="button" id="btnAddressRemove" class="btn btn-danger" ng-click="btnAddressRemove_click()" ng-disabled="AddressControls.length==1">
				<span class="glyphicon glyphicon-minus" aria-hidden="true" style="font-size:1.2em"></span>
			</button>
    </div>
  </div>
  <hr />

  <fieldset class="row " id="Address" ng-repeat="item in AddressControls track by $index" ng-disabled="$first">

    <div class="col-sm-1">
      <div class="form-group">

        <label>
				prefix
				</label>
      </div>
    </div>
    <div class="col-sm-3">
      <div class="form-group">
        <span></span>
        <select class="form-control" ng-model="item.prefixSelecteditem" ng-options="prefix.Title for prefix in AddressPrefix | filter: myFilter($index)">
					<option value="">--select option--</option>
				</select>
      </div>
    </div>
    <div class="col-sm-4">
      <div class="form-group">
        <div class="errorBlock">
        </div>
        <input class="form-control" type="text" value="" style="height:32px">
      </div>
    </div>

  </fieldset>


</body>

</html>

Method 1 CodePen

Method 2: Using Angular Filter In Controller

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

MainApplication.controller('mainController', ['$scope', function($scope) {
  $scope.AddressPrefix = [{
    id: 1,
    Title: 'AAA',
    priority: 1
  }, {
    id: 1,
    Title: 'BBB',
    priority: 2
  }, {
    id: 1,
    Title: 'CCC',
    priority: 3
  }, {
    id: 1,
    Title: 'DDD',
    priority: 4
  }, {
    id: 1,
    Title: 'EEE',
    priority: 5
  }, {
    id: 1,
    Title: 'FFF',
    priority: 6
  }, {
    id: 1,
    Title: 'GGG',
    priority: 7
  }, {
    id: 1,
    Title: 'HHH',
    priority: 8
  }, {
    id: 1,
    Title: 'III',
    priority: 2
  }, {
    id: 1,
    Title: 'jjj',
    priority: 2
  }, {
    id: 1,
    Title: 'kkk',
    priority: 2
  }, {
    id: 1,
    Title: 'LLL',
    priority: 10
  }, {
    id: 1,
    Title: 'MMM',
    priority: 9
  }, {
    id: 1,
    Title: 'ooo',
    priority: 7
  }, {
    id: 1,
    Title: 'PPP',
    priority: 12
  }, {
    id: 1,
    Title: 'qqq',
    priority: 3
  }, {
    id: 1,
    Title: 'RRR',
    priority: 13
  }, {
    id: 1,
    Title: 'zzz',
    priority: 14
  }, ];

  $scope.AddressControls = [{
    id: 1
  }];
  $scope.btnAddressAdd_click = function() {
    var newItemNo = $scope.AddressControls.length + 1
    $scope.AddressControls.push({
      'id': newItemNo
    });
  };
  $scope.btnAddressRemove_click = function() {
    $scope.AddressControls.pop();
  };

  $scope.myFilter = function(arr, index) {
    var lastSelectedOption = (index > 0) && $scope.AddressControls[index - 1] && $scope.AddressControls[index - 1].prefixSelecteditem;
    if (!lastSelectedOption) return arr;
    return arr.filter(function (option) {
      return option.priority > lastSelectedOption.priority;
    });
  }
}]);
<html ng-app="mainApplication">

<head>
  <title></title>

  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
</head>

<body dir="rtl" ng-controller="mainController">
  <div class="row">

    <div class="col-sm-6">
      <button type="button" id="btnAddressAdd" class="btn btn-primary" ng-click="btnAddressAdd_click()">
				<span class="glyphicon glyphicon glyphicon-plus" aria-hidden="true" style="font-size:1.2em"></span>
			</button>
      <button type="button" id="btnAddressRemove" class="btn btn-danger" ng-click="btnAddressRemove_click()" ng-disabled="AddressControls.length==1">
				<span class="glyphicon glyphicon-minus" aria-hidden="true" style="font-size:1.2em"></span>
			</button>
    </div>
  </div>
  <hr />

  <fieldset class="row " id="Address" ng-repeat="item in AddressControls track by $index" ng-disabled="$first">

    <div class="col-sm-1">
      <div class="form-group">

        <label>
				prefix
				</label>
      </div>
    </div>
    <div class="col-sm-3">
      <div class="form-group">
        <span></span>
        <select class="form-control" ng-model="item.prefixSelecteditem" ng-options="prefix.Title for prefix in myFilter(AddressPrefix, $index)">
					<option value="">--select option--</option>
				</select>
      </div>
    </div>
    <div class="col-sm-4">
      <div class="form-group">
        <div class="errorBlock">
        </div>
        <input class="form-control" type="text" value="" style="height:32px">
      </div>
    </div>

  </fieldset>


</body>

</html>

Method 2 CodePen

In first one we use angular filter to filter the options array, and in the second, we simply pass our array to a function in controller and return just the options we needed to show.

I think the first method is the better way, but the second one is simpler and easier to understand!

Edit: The solution for your Edit session is here!

Comments