Filter an array of objects by an array in AngularJS
welcome to CodeReview :-)

Firstly, I would mention that your $item and $model parameters should just be item and model. The dollar-sign prefix is conventionally reserved for official vendor libraries from Angular, and should not be used in your code to prevent confusion. I initially thought $model was a derivative of ngModel!

Secondly, do you need selectedIds? Can you not just use a function to extract those IDs? You do not need to watch a seperate array of IDs.

Thirdly - delete result.data[key] - this is not how you use delete. You use delete to remove properties from objects, not key/value pairs from collections. Instead, you should just set it to undefined.. with that said, you don't even need to use delete here anyway.

Fourthly.. what the hell is going on with for(key in result.data) if(result.data.hasOwnProperty(key)... that code is iterating the data then checking that the data has that property. wat. This works for circumventing prototypal inheritance, however you can just as easily use Object.keys(). Not to mention that the result of a $http request is only going to inherit from Object.

With that said, here's a refactor of your code. You will need lodash for this code to work, but no worries - lodash is probably the most handy library you will ever come across in JS. I use it on every project these days.

$scope.usersList = {
  items: [],
  search: function(term) {
    if(term.length &gt; 2) {
      UsersService.lookup(term)
        .then(function(xhr) {
          return _.reject(xhr.data, function(item) {
            return _.contains($scope.usersList.items, item);
          });
        })
        .then(function(data) {
          $scope.usersList.items = data;
        });
    }
  }
};


I've removed the select, remove and extractId functions as they do nothing in my example (and they did nothing anyway!)

This could definitely be refactored even better in my opinion, but I would need more scope on the actual problem to do that. For example, there's no need to use the $scope here aside from exposing the results to the view. This would be much better done if it was encapsulated inside of a function and only the result was exposed. This should really be in two separate classes at least.