Angular JS 在 ng-click 上向下拉菜单添加选项无法正常工作
我对
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 行找到
null
的
name
。图片
奇怪的错误
显示了这种情况。
您的代码有两个缺陷。
第一个缺陷是,您在
addOptions()
中将同一个对象推送到
left
和
right
数组中。这意味着当您禁用右侧的对象时,左侧的对象也会自动禁用(因为它们是同一个对象,而不仅仅是两个看起来相同的对象)。当它被禁用时,
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
您有两个
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
。
无需在 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));
};