当模型元素与模型数组拼接时,AngularJS:ng-repeat列表不会更新

我有两个控制器,并使用app.factory函数在它们之间共享数据。

第一个控制器在单击链接时在模型数组(pluginsDisplayed)中添加一个小部件。 该小部件被推入到数组中,这个变化反映到视图中(使用ng-repeat显示数组内容):

<div ng-repeat="pluginD in pluginsDisplayed"> <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div> </div> 

小部件是build立在三个指令,k2plugin,删除和resize。 remove指令为k2plugin指令的模板添加一个span。 当单击所述跨度时,使用Array.splice()删除共享数组中的正确元素。 共享数组已正确更新,但更改反映在视图中。 但是,当添加另一个元素时,在删除之后,视图将被正确刷新,并且不会显示之前删除的元素。

我错了什么? 你能解释一下为什么这不起作用吗? 有没有更好的方法来做我想用AngularJS做什么?

这是我的index.html:

 <!doctype html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"> </script> <script src="main.js"></script> </head> <body> <div ng-app="livePlugins"> <div ng-controller="pluginlistctrl"> <span>Add one of {{pluginList.length}} plugins</span> <li ng-repeat="plugin in pluginList"> <span><a href="" ng-click="add()">{{plugin.name}}</a></span> </li> </div> <div ng-controller="k2ctrl"> <div ng-repeat="pluginD in pluginsDisplayed"> <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div> </div> </div> </div> </body> </html> 

这是我的main.js:

 var app = angular.module ("livePlugins",[]); app.factory('Data', function () { return {pluginsDisplayed: []}; }); app.controller ("pluginlistctrl", function ($scope, Data) { $scope.pluginList = [{name: "plugin1"}, {name:"plugin2"}, {name:"plugin3"}]; $scope.add = function () { console.log ("Called add on", this.plugin.name, this.pluginList); var newPlugin = {}; newPlugin.id = this.plugin.name + '_' + (new Date()).getTime(); newPlugin.name = this.plugin.name; Data.pluginsDisplayed.push (newPlugin); } }) app.controller ("k2ctrl", function ($scope, Data) { $scope.pluginsDisplayed = Data.pluginsDisplayed; $scope.remove = function (element) { console.log ("Called remove on ", this.pluginid, element); var len = $scope.pluginsDisplayed.length; var index = -1; // Find the element in the array for (var i = 0; i < len; i += 1) { if ($scope.pluginsDisplayed[i].id === this.pluginid) { index = i; break; } } // Remove the element if (index !== -1) { console.log ("removing the element from the array, index: ", index); $scope.pluginsDisplayed.splice(index,1); } } $scope.resize = function () { console.log ("Called resize on ", this.pluginid); } }) app.directive("k2plugin", function () { return { restrict: "A", scope: true, link: function (scope, elements, attrs) { console.log ("creating plugin"); // This won't work immediately. Attribute pluginname will be undefined // as soon as this is called. scope.pluginname = "Loading..."; scope.pluginid = attrs.pluginid; // Observe changes to interpolated attribute attrs.$observe('pluginname', function(value) { console.log('pluginname has changed value to ' + value); scope.pluginname = attrs.pluginname; }); // Observe changes to interpolated attribute attrs.$observe('pluginid', function(value) { console.log('pluginid has changed value to ' + value); scope.pluginid = attrs.pluginid; }); }, template: "<div>{{pluginname}} <span resize>_</span> <span remove>X</span>" + "<div>Plugin DIV</div>" + "</div>", replace: true }; }); app.directive("remove", function () { return function (scope, element, attrs) { element.bind ("mousedown", function () { scope.remove(element); }) }; }); app.directive("resize", function () { return function (scope, element, attrs) { element.bind ("mousedown", function () { scope.resize(element); }) }; }); 

每当你在AngularJS之外做某种forms的操作时,比如用jQuery做一个Ajax调用,或者把一个事件绑定到像你这样的元素,你需要让AngularJS知道自己的更新。 以下是您需要执行的代码更改:

 app.directive("remove", function () { return function (scope, element, attrs) { element.bind ("mousedown", function () { scope.remove(element); scope.$apply(); }) }; }); app.directive("resize", function () { return function (scope, element, attrs) { element.bind ("mousedown", function () { scope.resize(element); scope.$apply(); }) }; }); 

这里是它的文档: https : //docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply

如果你添加一个$scope.$apply();$scope.pluginsDisplayed.splice(index,1); 那么它的工作。

我不知道为什么会发生这种情况,但基本上当AngularJS不知道$ scope已经改变时,它需要手动调用$ apply。 我也是AngularJS的新手,所以无法更好地解释这一点。 我也需要更多的注意。

我发现这个很棒的文章 ,解释得相当不错。 注意:我认为使用ng-click (docs)而不是绑定到“mousedown”可能会更好。 我在这里写了一个简单的应用程序( http://avinash.me/losh ,来源http://github.com/hardfire/losh )基于AngularJS。 它不是很干净,但可能有帮助。

我遇到过同样的问题。 问题是因为'ng-controller'被定义了两次(在路由和HTML中)。

有一个简单的方法来做到这一点。 好简单。 因为我注意到了

 $scope.yourModel = []; 

删除所有$ scope.yourModel数组列表,你可以这样做

 function deleteAnObjectByKey(objects, key) { var clonedObjects = Object.assign({}, objects); for (var x in clonedObjects) if (clonedObjects.hasOwnProperty(x)) if (clonedObjects[x].id == key) delete clonedObjects[x]; $scope.yourModel = clonedObjects; } 

$ scope.yourModel将被克隆的对象更新。

希望有所帮助。