1

I have an array of objects in $scope.currentSChannels.scgsLink This array of objects have something like

$scope.currentSChannels.scgsLink = [{channelId:1, sCgsLinkId:1, groupNo:1, percentage: 50, expireHrs:4},{channelId:1, sCgsLinkId:2, groupNo:2, percentage:50, expireHrs:1}]

and I also have the following select list

<div class="col-md-4">
                <select class="form-control" ng-model="newLink.groupNo"
                        name="groupNo" id="groupNo" 
                        ng-options="t.value as t.text for t in metaData.spGroups"></select>
            </div>

I need to filter that list to not show already selected items in the $scope.currentSChannels.scgsLink groupNo column. I looked at http://christian.fei.ninja/Angular-Filter-already-selected-items-from-ng-options/ and also at AngularJS ng-options to exclude specific object and both seem to be close but not enough as I need to filter against an array and a particular column in that array. How should I implement that filtering?

Community
  • 1
  • 1
Naomi
  • 718
  • 1
  • 9
  • 28

2 Answers2

2

The template is getting a bit tricky. Assuming selectedLink is the variable that points to the selected groupNo

ng-options="t.value as t.text for t in metaData.spGroups | filter: {value: '!' + currentSChannels.scgsLink[selectedLink].groupNo}"

See this fiddle : the second select contains the same collection as the first one, excluded what is already selected.

Edit: Solution above is for excluding elements according to one value. So as to exclude the elements according to a collection of values, a custom filter would suit best:

Filter

app.filter('channelFilter', function () {
    return function (metadata, exclusions) {
        var filterFunction = function (metadata) {
            // return the metadata object if exclusions array does NOT contain his groupNo
            return !exclusions.some(function (exclusion) {  
                return exclusion.groupNo === metadata.value;
            });
        };

        return metadatas.filter(filterFunction);
    };
});

Usage

ng-options="metadata in metadatas | channelFilter: exclusions"

Template

ng-options="t.value as t.text for t in metaData.spGroups | channelFilter: currentSChannels.scgsLink"

Fiddle

That said, would be more efficient to group selected links by groupNo to avoid searches in the array, and filter in the controller.

Michel
  • 26,600
  • 6
  • 64
  • 69
  • What is selectedLink in your example? I want to implement NOT IN filter where I want to exclude all already selected groups. As I shown in my example, I already have 2 groups assigned. I want to allow to select only groups which are not already in that complex property (that property is an array of objects as I've shown). – Naomi Oct 26 '15 at 19:03
  • *"I need to filter against an array and a particular column in that array"*. According to the sentence I thought you needed to filter against one item only. If you need to filter against all elements of `scgsLink`, I would define a custom filter... – Michel Oct 26 '15 at 19:06
  • That's what I was thinking as well, but that sample in the blog post is not clear to me. It also seems to work for one item only. Can you help me writing this custom filter where I would pass an array and a particular column in array to work against? – Naomi Oct 26 '15 at 19:09
  • Yep. Btw do you have in your project any js library like lodash or underscore? – Michel Oct 26 '15 at 19:19
  • I've searched solution and we don't use underscore.js although I see few comments telling the code is borrowed from it. We do use lodash already – Naomi Oct 26 '15 at 19:35
  • Please see edit. This is done in plain js, without library. I've asked just in case, for optimization purpose (there is a `groupBy` function in lodash). – Michel Oct 26 '15 at 19:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93407/discussion-between-naomi-and-michael-p-bazos). – Naomi Oct 26 '15 at 19:59
1

I wanted to make it a bit more generic, so I've done the following

http://jsfiddle.net/96m4sfu8/

app.filter('excludeFrom', function () {
    return function (inputArray, excludeArray, excludeColumnName, inputColumnName) {
        if (inputColumnName==undefined)
            inputColumnName = 'value';
  var filterFunction = function (inputItem) {
            return !excludeArray.some(function (excludeItem) {
                return excludeItem[excludeColumnName] === inputItem[inputColumnName];
            });
        };

        return inputArray.filter(filterFunction);
    };
});
Naomi
  • 718
  • 1
  • 9
  • 28