amin365
amin365

Reputation: 196

Adding filter to a list of select box options in Angular

I am trying to filter what options appear in a select box that is generated using ng-repeat. If a particular option has been selected in one select box, it should not show up in the other appended select boxes. I tried using a custom filter but it's resulting in a syntax error from angular.

<html ng-app="myApp" ng-controller="myCtrl">
<head>
   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js">   </script>
   <script src="app.js"></script>
</head>
<body>
    <ul>
        <li ng-repeat="element in segments">
            <input type="text" name="comment" ng-model="element.comment">

            <select name="mySelect" id="mySelect" ng-options="employee.name for employee in employeeList|selected track by employee.name" ng-model="employeeName" ng-change="exclude(employeeName.name)"></select>
        </li>
    </ul>
    <button type="button" ng-click="addSegment()">Add segment</button>
</body>
</html>

and here is the script

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

myApp.controller('myCtrl', function($scope) {
    $scope.segmentId = 0;
    $scope.segments = [];
    $scope.employeeList = [{'name' : 'jhon','isAssigned' : 0},{'name' :'wayne','isAssigned' : 0},{'name' : 'clark','isAssigned' : 0}];
    $scope.addSegment = function () {
        var segment = {
            'id' : $scope.segmentId,
            'assignedTo' : null,
            'comment' : null
        };
        $scope.segments.push(segment);
        $scope.segmentId++;
        console.log($scope.employeeList);
    };
    $scope.exclude = function (userName) {
        for (var i = 0; i < $scope.employeeList.length; i++) {
        var employee = $scope.employeeList[i].name;
        if (employee == userName) {
            $scope.employeeList[i].isAssigned = 1;
        }
    }
};

});

myApp.filter('selected', function() {
   return function() {
     if(employee.isAssigned == 0) {
        return employee;
     }
   return;
 };
 });

Upvotes: 0

Views: 423

Answers (3)

atefth
atefth

Reputation: 1623

You'll need to use a directive along with a filter I'm guessing at first look. I'm sure this can be optimised and in fact I leave that as an exercise for yourself.

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

myApp.controller('myCtrl', function($scope) {
    // The array where the selections are being kept
    $scope.segments = [0];
    $scope.segment = {item: undefined};
    // The list from which the select field is being populated
    $scope.list = [{name: 'one'}, {name: 'two'}, {name: 'three'}, {name: 'four'}];
    // When you add a selection to the segments array
    $scope.addSegment = function () {
        if ($scope.segment != undefined && $scope.segment.item != undefined && $scope.segment.item != '') {
            $scope.segments.push($scope.segment);
            $scope.selected = '';
            $scope.segment = {item: undefined};
        }
    };

    // We are using this function to dynamically set the selected item
    $scope.setItem = function (item) {
        $scope.segment = {item};
    };
});

// The directive that allows you to have an isolcated scope
myApp.directive('item', function () {
    return {
        template: '<select ng-options="employee.name for employee in list| hideSelected:segments:index:selected" ng-model="selected" ng-change="setItem"></select>',
        restrict: 'E',
        scope: {
            list: '=',
            selected: '=',
            segments: '=',
            index: '=',
            setItem: '='
        },
        replace: true
    };
});

// The filter that looks complicated but worls nonetheless ;)
myApp.filter('hideSelected', function () {
    return function (list, segments, i, selected) {
        array = [];
        looped = false;
        angular.forEach(list, function (item, key) {
            duplicate = false;
            angular.forEach(segments, function (segment, index) {
                looped = true;
                if (segment != 0 && item.name == segment.item.name && selected.name != item.name) {
                    duplicate = true;
                }
            });
            if (!duplicate) {
                array.push(item);
            }
        });
        if (!looped) {
            return list;
        }else{
            return array;
        }
    };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="myApp" ng-controller="myCtrl">
    <body>
        <ul>
            <li ng-repeat="element in segments track by $index">
                <item list="list" set-item="setItem(selected)" selected="selected" index="$index" segments="segments"></item>
            </li>
        </ul>
        <button type="button" ng-click="addSegment()">Add segment</button>
        <script src="app.js" type="text/javascript" charset="utf-8"></script>
    </body>
</html>

The Directive

  • Uses a simple inline template
  • Creates an isolate scope for the directive

The Filter

  • Goes through the list items and the selected items in the segments array

  • Checks whether to show the item in loop or not

If and when you find a more elegant solution, please do share it with us!

Hope I could help :)

Upvotes: 3

Anik Islam Abhi
Anik Islam Abhi

Reputation: 25352

You didn't pass employee in your function

Try like this

myApp.filter('selected', function() {
  return function(employee) {
   return employee.isAssigned == 0 ;
  };
});

Upvotes: 2

Hadi
Hadi

Reputation: 17299

you can use this format of filter for this. try this.

  <select name="mySelect" id="mySelect" ng-options="employee.name for employee in modal.employeeList | filter:{isAssigned:0}" ng-model="employeeName" ng-></select>

var myapp = angular.module('app', []);
myapp.controller('Main', function ($scope) {
 var vm = this;
   vm.employeeList = [{'name' : 'jhon','isAssigned' : 1},{'name' :'wayne','isAssigned' : 0},{'name' : 'clark','isAssigned' : 0}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app = "app">
  <div ng-controller="Main as ctrl">
<div class="select-style">
   <select name="mySelect" id="mySelect" ng-options="employee.name for employee in ctrl.employeeList | filter:{isAssigned:0}" ng-model="employeeName" ng-change="exclude(employeeName.name)"></select>
</div>
   </div>
</div>

Upvotes: 1

Related Questions