Question

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

Était-ce utile?

La solution

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;
};

Autres conseils

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top