当推送到数组时,indexOf()== -1似乎不起作用

时间:2015-04-12 23:06:44

标签: javascript angularjs

当我在输入框中输入时,我有一个数组被过滤/搜索。当我点击返回时,输入文本被附加到数组。这一切都很棒,而且很有效。

什么是无效的是$ scope.list.indexOf()== -1,它应该阻止我输入重复项。但它不起作用。

我哪里错了?

HTML

<!doctype html>
<html ng-app="bgApp">
<head>
<title>List & Tag</title>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">

<!-- Local CSS -->
<link rel="stylesheet" type="text/css"  href="./static/css/dev-style.css" />
</head>

<body>
<div ng-controller="listController">
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 div-title">
            <div class="col-xs-6 col-sm-6 col-md-6">
                <h1><small>{{title}}</small></h1>
                <input type="text" ng-enter="addItem()" ng-model="addName" class="search-query" placeholder="Search">
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 div-title">
            <div class="col-xs-3 col-sm-3 col-md-3">Name of Item</div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 div-row" ng-repeat="item in list | filter:addName">
            <div class="col-xs-3 col-sm-3 col-md-3">{{ item.name }}</div>
        </div>
    </div>
</div>




<!-- AngularJS scripts from CDN -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular-resource.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular-animate.min.js"></script>

<!-- JQuery scripts from CDN -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

<!-- Bootstrap scripts compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>

<!-- Locally installed scripts --> 
<script src="./js/bgapp.js"></script>
</body>

</html>

APP,指令&amp;控制器

var bgapp = angular.module('bgApp', [])

.directive('ngEnter', function () {
    return function (scope, element, attrs) {
        element.bind("keydown keypress", function (event) {
            if (event.which === 13) {
                scope.$apply(function () {
                    scope.$eval(attrs.ngEnter, {
                        'event': event
                    });
                });

                event.preventDefault();
            }
        });
    };
});

bgapp.controller('listController', ['$scope', function($scope) {

    $scope.title = 'Recent Activity';

    $scope.list = [
        {name: 'User 1'},
        {name: 'Admin 1'},
        {name: 'Service 1'},
        {name: 'Project 1'},
        {name: 'Configuration Item 1'},
        {name: 'Task 1'},
        {name: 'Incident 1'},
        {name: 'Issue 1'},
        {name: 'Known Issue 1'},
        {name: 'Problem 1'},
        {name: 'Knowledge Base 1'},
        {name: 'Update 1'},
        {name: 'Document 1'},
        ];

    $scope.addItem = function() {
        var elem = {name: $scope.addName};
        if ($scope.list.indexOf(elem) == -1) {
            $scope.list.push(
                elem
            );
        }    
    };

}]);

5 个答案:

答案 0 :(得分:1)

由于$scope.listObject的列表,因此测试$scope.list.indexOf(elem)适用于2 Object的引用,这些引用始终是不同的。

您可以使用AngularJS中的$filter('filter')(array, expression, comparator)

$scope.addItem = function() {
    var elem = {name: $scope.addName};
    if ($filter('filter')($scope.list, {name: elem.name}).length == 0) {
        $scope.list.push(
            elem
        );
    }    
};

答案 1 :(得分:1)

Javascript不认为对象是相同的,因为它们不是同一个实例。 This link很好地解释了。

我建议使用下划线的findWhere来测试是否存在具有相同属性的对象。

在你的情况下:

if (_.findWhere($scope.list, elem) === undefined){
   $scope.list.push(elem);
}

当然,您需要包含下划线才能使用它。由于您正在使用角度,因此您可能希望使用此:

https://github.com/floydsoft/angular-underscore

答案 2 :(得分:0)

远离计算机,所以我采取了刺,但似乎你正在尝试对某个对象(项目列表)执行字符串操作。

答案 3 :(得分:0)

$scope.addItem = function() {
    var elem = {name: $scope.addName};
    if ($scope.listHasElement($scope.list, elem)) {
        $scope.list.push(elem);
    }    
};

$scope.listHasElement = function (list, new) {
    for (index = 0; index < list.length; ++index) {
        if(list[index].name == new.name) return true;
    }
    return false;
}

试试这个,我现在无法测试它,但我猜它是问题的解决方案。

答案 4 :(得分:0)

您当前的indexOf失败了,因为没有两个对象是相同的,除非它们是相同的引用,即{} !== {}但是var o = {}; o === o;

在您尝试查找引用时,了解对象最初是如何创建的,并且 Object 可以序列化为JSON而不会抛出错误,您可以使用最后一个点来执行{{ 1}}用于字符串而不是

例如,使用Array.prototype.map

indexOf

你也可以类似地使用Array.prototype.some,它可以在第一场比赛结束时(相对于上面的function serialisedIndexOf(haystack, needle) { return haystack.map(JSON.stringify).indexOf(JSON.stringify(needle)); } var arr = [[1], [2], [3]]; serialisedIndexOf( arr, [2] ); // 1 // so the original reference for [2] can be obtained at arr[1] ,它总是会至少经过一次数组中的每一项),但需要更多的代码来实现

.map

ES6 中,我们将Array.prototype.findIndex可以为我们提供function serialisedIndexOf(haystack, needle) { var i, r; needle = JSON.stringify(needle); r = haystack.some(function (e, idx) { i = idx; return JSON.stringify(e) === needle; }); return r ? i : -1; } 方法的较短版本,但您不应该假设浏览器支持

.some