开发者问题收集

Angular JS 在 ng-click 上向下拉菜单添加选项无法正常工作

2017-01-10
257

我对 angularJS 还很陌生。我正在尝试为用户创建一个界面,让用户能够从两个下拉列表中精确选择两个项目。它们实际上是相同的选项。当用户从左侧下拉列表中选择某个选项时,他将无法从右侧下拉列表中选择相同的选项,反之亦然。用户还将有一个按钮来添加更多选项。该代码适用于所有情况,但当用户单击按钮添加更多选项时,新添加的选项根本不起作用。 这是我的完整代码:

   <html>

<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
</head>
<body>
<div ng-app="app">
    <div ng-controller="MyCtrl">
        <h2>Select one Item from left and one Item from right</h2>
        <select ng-model="leftmodel"
                ng-change="ChangeOptions()"
                ng-options="option as option.value disable
  when option.disabled for option in left">
        </select>

        <select ng-model="rightmodel"
                ng-change="ChangeOptions()"
                ng-options="option as option.value disable when option.disabled for option in right">

        </select>
        <button ng-click="addOptions()">Click Me</button>
    </div>
</div>
<script>
    var module = angular.module("app", []);
    module.controller("MyCtrl",
            function($scope) {
                $scope.left = [{
                    "name": "apple",
                    "value": "Nice Apple",
                    "disabled": false
                }, {
                    "name": "orange",
                    "value": "Yellow Orange",
                    "disabled": true
                }, {
                    "name": "berry",
                    "value": "Blue Berry",
                    "disabled": false
                }];

                $scope.right = [{
                    "name": "apple",
                    "value": "Nice Apple",
                    "disabled": true
                }, {
                    "name": "orange",
                    "value": "Yellow Orange",
                    "disabled": false
                }, {
                    "name": "berry",
                    "value": "Blue Berry",
                    "disabled": false
                }];

                $scope.leftmodel = $scope.left[0];
                $scope.rightmodel = $scope.right[1];
                $scope.addOptions=function()
                {
                    var banana={
                        "name": "banana",
                        "value": "Tasty Banana",
                        "disabled": false
                    };
                    var orange={
                        "name":"orange",
                        "value":"Soour Orange",
                        "disabled":false
                    };
                    $scope.left.push(banana);
                    $scope.left.push(orange);
                    $scope.right.push(banana);
                    $scope.right.push(orange);
                };
                $scope.ChangeOptions = function() {
                    var lsize = $scope.left.length;
                    var rsize = $scope.left.length;
                    for (var i = 0; i < lsize; i++) {

                        console.log($scope.left[i]);
                        if ($scope.left[i].name === $scope.rightmodel.name) {
                            $scope.left[i].disabled = true;
                        } else {
                            $scope.left[i].disabled = false;
                        }
                    }

                    for (var i = 0; i < rsize; i++) {
                        if ($scope.right[i].name === $scope.leftmodel.name) {
                            $scope.right[i].disabled = true;
                        } else {
                            $scope.right[i].disabled = false;
                        }
                    }
                };

            }
    );
</script>
</body>
</html>

我还有一个 Codepen 。 单击按钮时单击新创建的选项后出现的错误是:

TypeError: Cannot read property 'name' of null at ChildScope.$scope.ChangeOptions (first.html:89) at fn (eval at compile (angular.js:15156), :4:159) at ChildScope.$eval (angular.js:17972) at angular.js:25711 at Object. (angular.js:28536) at forEach (angular.js:357) at Object.$$writeModelToScope (angular.js:28534) at writeToModelIfNeeded (angular.js:28527) at angular.js:28521 at validationDone (angular.js:28446)

有人能帮我吗,我该如何解决这个问题?提前致谢。

我注意到了另一件奇怪的事情。它可以在第 88 行控制名称。但它在同一行失败,说它无法在第 88 行找到 nullname 。图片 奇怪的错误 显示了这种情况。

3个回答

您的代码有两个缺陷。

第一个缺陷是,您在 addOptions() 中将同一个对象推送到 leftright 数组中。这意味着当您禁用右侧的对象时,左侧的对象也会自动禁用(因为它们是同一个对象,而不仅仅是两个看起来相同的对象)。当它被禁用时, leftmodel 不再是有效选项,因此它会变为 undefined

您可以使用 angular.copy() 克隆对象来更正此问题,从而在左侧和右侧创建两个不同的对象。

您的第二个问题是,您的列表中已经有一个名为 'orange' 的项目,因此如果您选择 left 上的其中一个,它会禁用 right 上的 both ,并导致 leftmodel 变为 undefined (因为第一个 'orange'right 的默认选项)。

这里是更新的 addOptions()

$scope.addOptions = function() {
  var banana = {
    "name": "banana",
    "value": "Tasty Banana",
    "disabled": false
  };
  var orange = {
    "name": "sorange",
    "value": "Soour Orange",
    "disabled": false
  };
  $scope.left.push(angular.copy(banana));
  $scope.left.push(angular.copy(orange));
  $scope.right.push(angular.copy(banana));
  $scope.right.push(angular.copy(orange));
};

以及您的 codepen 的分支: https://codepen.io/anon/pen/xgZYmW

Claies
2017-01-11

您有两个 for 循环,它们都使用变量 i 作为索引。JavaScript 实际上将这些变量移动到范围的顶部,因此解释器将创建类似以下内容的内容:

$scope.ChangeOptions = function() {
    var lsize = $scope.left.length;
    var rsize = $scope.left.length;

    var i = 0;
    var i = 0;

    for(i; i < lsize; i++) {
        //
    }

    // After the previous loop, i will be 3
    for(i; i < rsize; i++) {

这将导致第二个循环从 i = 3 开始,因此它找不到 $scope.right[3].name 。要解决此问题,只需将第二个循环更改为另一个变量,例如 j

devqon
2017-01-10

无需在 addOptions 方法中初始化新变量。获取 HTML 中已定义的两个模型,然后使用函数将它们添加到数组中:

   $scope.addOptions=function()
            {
                var leftOption = $scope.leftmodel;
                var rightOption = $scope.rightmodel; 

                function newFruit(option){

                    var fruit = {
                    "name": option,
                    "value": "",
                    "disabled": false

                  };

                  return fruit;
                }

                $scope.left.push(newFruit(leftOption));
                $scope.right.push(newFruit(rightOption));
            };
23rharris
2017-01-10