我有两个控制器,并使用app.factory函数在它们之间共享数据。
第一个控制器在单击链接时在模型数组(pluginsDisplayed)中添加一个小部件。小部件被推入数组,此更改将反映到视图中(使用ng-repeat显示数组内容):
<div ng-repeat="pluginD in pluginsDisplayed">
<div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>
小部件基于三个指令构建,k2plugin,remove和resize。 remove指令将span添加到k2plugin指令的模板中。单击所述跨度后,将使用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);
})
};
});
答案 0 :(得分:132)
每当你在AngularJS之外进行某种形式的操作时,例如用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
答案 1 :(得分:54)
如果您在$scope.$apply();
之后添加$scope.pluginsDisplayed.splice(index,1);
,那就可以了。
我不确定为什么会发生这种情况,但基本上当AngularJS不知道$ scope已经改变时,它需要手动调用$ apply。我也是AngularJS的新手,所以无法更好地解释这一点。我也需要更多地了解它。
我发现this awesome article能够很好地解释它。 注意:我认为使用ng-click (docs)而不是绑定到“mousedown”可能更好。我在这里写了一个简单的应用程序(http://avinash.me/losh,源http://github.com/hardfire/losh),基于AngularJS。它不是很干净,但它可能会有所帮助。
答案 2 :(得分:7)
我有同样的问题。问题是因为&#39; ng-controller&#39;定义了两次(在路由中以及在HTML中)。
答案 3 :(得分:0)
这是一种简单的方法。很容易。因为我注意到了
$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;
}
将使用clonedObjects更新$ scope.yourModel。
希望有所帮助。
答案 4 :(得分:0)
从ng-repeat中删除“按索引跟踪”,它将刷新DOM