我有一个items
循环,需要通过API动态替换。问题是外部作用域在替换时似乎松散了对原始对象的引用。如何让外部作用域注意到数组中某个项的值的变化?
(function(ng) {
'use strict';
ng.module('app', [])
.controller('ParentController', ['$scope',
function($scope) {
$scope.items = [{
name: "Foo",
number: 0
}, {
name: "Bar",
number: 1
}, {
name: "Baz",
number: 1
}];
}
])
.controller('ItemController', ['$scope',
function($scope) {
// fake code, would get from API normally
var getFromApi = function() {
return {
name: $scope.item.name,
number: $scope.item.number + 1
};
}
$scope.incr = function() {
$scope.item = getFromApi();
}
}
]);
})(window.angular);

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="ParentController">
<p>When you click one of the below buttons</p>
<ul>
<li ng-repeat="item in items" ng-controller="ItemController">
{{item.name}} ({{item.number}})
<button ng-click="incr()">+</button>
</li>
</ul>
<p>This should update</p>
<p>{{items}}</p>
<p>...but it doesn't</p>
</div>
</body>
</html>
&#13;
答案 0 :(得分:0)
您需要知道该项目的键,您要更改其属性,然后更改该集合中的此项。
要声明密钥,您可以使用 ng-repeat="(key, item) in items"
。然后,密钥将在$scope.key
中以ItemController
显示。
接下来ItemController
继承了$scope
的{{1}},您可以直接访问ParentController
中的$scope.items
:
<强> ItemController.js:强>
ItemController
只有在ItemController是ParentController的Child或者否则继承它的范围时,这才有可能。
您可以看到脚本运行如下:
$scope.incr = function() {
$scope.items[$scope.key] = getFromApi();
}
(function(ng) {
'use strict';
ng.module('app', [])
.controller('ParentController', ['$scope',
function($scope) {
$scope.items = [{
name: "Foo",
number: 0
}, {
name: "Bar",
number: 1
}, {
name: "Baz",
number: 1
}];
}
])
.controller('ItemController', ['$scope',
function($scope) {
// fake code, would get from API normally
var getFromApi = function() {
return {
name: $scope.item.name,
number: $scope.item.number + 1
};
}
$scope.incr = function() {
$scope.items[$scope.key] = getFromApi();
}
}
]);
})(window.angular);
答案 1 :(得分:0)
您可以使用父数组中项目的索引来替换它
(function(ng) {
'use strict';
ng.module('app', [])
.controller('ParentController', ['$scope',
function($scope) {
$scope.items = [{
name: "Foo",
number: 0
}, {
name: "Bar",
number: 1
}, {
name: "Baz",
number: 1
}];
}
])
.controller('ItemController', ['$scope',
function($scope) {
// fake code, would get from API normally
var getFromApi = function() {
return {
name: $scope.item.name,
number: $scope.item.number + 1
};
}
$scope.incr = function() {
$scope.$parent.items[$scope.$index] = getFromApi();
}
}
]);
})(window.angular);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="ParentController">
<p>When you click one of the below buttons</p>
<ul>
<li ng-repeat="item in items track by $index" ng-controller="ItemController">
{{item.name}} ({{item.number}}) {{$index}}
<button ng-click="incr()">+</button>
</li>
</ul>
<p>This should update</p>
<p>{{items}}</p>
<p>...but it doesn't</p>
</div>
</body>
</html>
&#13;
答案 2 :(得分:0)
您可以将API调用逻辑移动到父控制器,有关示例,请参阅the JSFiddle demo,或者至少替换父作用域中$scope.items
数组中的已修改元素。
编辑:在此处废弃我之前的陈述,但它无效的共鸣是因为当您在子范围$scope.item
方法中指定incr()
时,您和&#39} #39;不要修改$scope.items
数组。您只是在子范围内更改变量赋值。
因此,在incr()
调用之前,内存中的变量赋值可能如下所示:
$scope.items =
item1 -> [ js obj 1 ]
item2 -> [ js obj 2 ]
item3 -> [ js obj 3 ]
$scope.item -> [ js obj 1 ]
在incr()
调用第一项后:
$scope.items =
item1 -> [ js obj 1 ] // still obj 1 here!
item2 -> [ js obj 2 ]
item3 -> [ js obj 3 ]
$scope.item -> [ js obj 4 ] // but entirely new obj here!
示例代码:
angular.module('app', [])
.controller('ParentController', ['$scope',
function ($scope) {
$scope.items = [{
name: "Foo",
number: 0
}, {
name: "Bar",
number: 1
}, {
name: "Baz",
number: 1
}];
// fake code, would get from API normally
var getFromApi = function (item) {
return {
name: item.name,
number: item.number + 1
};
}
$scope.updateItem = function (index) {
$scope.items[index] = getFromApi($scope.items[index]);
};
}])
.controller('ItemController', ['$scope',
function ($scope) {
$scope.incr = function (index) {
$scope.updateItem(index);
}
}]);
显然,如果您想以其他方式识别修改后的项目,则可以在不使用$index
的情况下离开。上面的代码只是解决您问题的最简单方法。您可能会将getFromApi()
保留在子范围内,并在那里使用$scope.items[$index] = getFromApi()
(感谢范围继承)。我发现在父范围内保持该方法更加干净。
答案 3 :(得分:0)
另一个(hacky)选项是简单地遍历新对象,分配旧的变量:
var newItem = getFromApi();
for (var key in newItem) {
$scope.item[key] = newItem[key];
}
(function(ng) {
'use strict';
ng.module('app', [])
.controller('ParentController', ['$scope',
function($scope) {
$scope.items = [{
name: "Foo",
number: 0
}, {
name: "Bar",
number: 1
}, {
name: "Baz",
number: 1
}];
}
])
.controller('ItemController', ['$scope',
function($scope) {
// fake code, would get from API normally
var getFromApi = function() {
return {
name: $scope.item.name,
number: $scope.item.number + 1
};
}
$scope.incr = function() {
var newItem = getFromApi();
for (var key in newItem) {
$scope.item[key] = newItem[key];
}
}
}
]);
})(window.angular);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="ParentController">
<p>When you click one of the below buttons</p>
<ul>
<li ng-repeat="item in items" ng-controller="ItemController">
{{item.name}} ({{item.number}})
<button ng-click="incr()">+</button>
</li>
</ul>
<p>This should update</p>
<p>{{items}}</p>
<p>...now it does!</p>
</div>
</body>
</html>
&#13;