Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have this angularjs array: $scope.fav = [] where items (objects) get added with to it on a function call. an example of these objects are {quote: "Some text", controller: some_controller} When I add a new object to the array, the array is saved in localstorage. The array works exactly how I want it to except when I try to print it in console.log() i get many [object, Object], which I just assumed is the way it is printed. This isn't the main issue though because the array works how it needs to.

The issue I am having is with trying to find if an object is already in an array. I have tried

if ($scope.fav.indexOf({quote: q, controller: c}) == -1)

and this did not seem to work because every object going in was index -1 even if it was already in the array. I presume this is because it is not reading the object correctly.

Lastly I have resorted to this function:

$scope.containsObject = function(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
    if (list[i] === obj) {
        return true;
    }
}

return false;

}

which checks if the object is in the array. Here is how I call it:

$scope.addToFav = function(q, c) {
    $scope.value = $scope.containsObject({quote: q, controller: c}, $scope.fav)
    console.log($scope.value);

}

I keep getting a negative value for $scope.value even if the object is in the array. Sorry for the long complicating explanation.

Thank you for your insight, Ben

share|improve this question
up vote 7 down vote accepted

Array.indexOf() and the === operator compare object references and are only true when comparing references to the same instance of an object. {quote: q, controller: c} is an entirely different object instance than those in the array, even if its properties match an object in the array exactly.

Angular has a helper function called angular.equals() that checks of 2 objects are equivalent. You can use it in place of the ===...

$scope.containsObject = function(obj, list) {
    var i;
    for (i = 0; i < list.length; i++) {
        if (angular.equals(list[i], obj)) {
            return true;
        }
    }

    return false;
};
share|improve this answer
    
Thank you so much for that Anthony, it was a fairly simple solution. Cheers, Ben – benjipelletier Apr 22 '14 at 5:25

Each time you're retrieving an object from local storage, you're actually creating a new object, probably using JSON.decode, to convert the string data stored in local storage, into an object.

Even if the new object contains the same data, it will fail the strict test === (and indeed, the loose ==) when compared to the existing (albeit apparently identical) object. indexOf uses the strict equality operator === so this would behave the same way.

So you need some code to test if an object is equal to another, and then apply it to a list. One way is to use a combination of angular.equals, which performs a deep comparison of objects, and filter:

$scope.containsObject = function(obj, list) {
  return list.filter(function(listItem) {
    return angular.equals(listItem, obj)
  }).length > 0;
}

The filter function I don't believe is part of IE8. If you need IE8 supported, you can use the polyfill, or use another library, like lo-dash

$scope.containsObject = function(obj, list) {
  return _.filter(list, function(listItem) {
    return angular.equals(listItem, obj)
  }).length > 0;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.