[英]Scope changes in directive's bind function are not reflected
I have a list of todo items with a delete button directive that looks like, 我有一个待办事项清单,其中包含删除按钮指令,如下所示:
Howerver, when i click on the trash button, the view is not getting refreshed with the new todos. 但是,当我单击垃圾箱按钮时,视图不会随着新的待办事项刷新。 I used
scope.$apply()
to force the digest cycle, still it doesn't work 我使用
scope.$apply()
强制了摘要循环,但仍然无法正常工作
HTML code, HTML代码
<div ng-controller="todoCtrl">
<ul>
<li ng-repeat="todo in todos">
<i class="fa fa-trash-o fa-lg" sk-del="{{todo}}" todos="todos"></i>{{todo}}
</li>
</ul>
</div>
Javascript code, Javascript代码
var app = angular.module('app', []);
app.controller('todoCtrl', function ($scope, $element) {
$scope.todos = ["eat", "pray", "live"]
})
app.directive("skDel", function(){
return {
scope:{
todos: '='
},
link: function(scope, elem, attr){
elem.bind("click", function(){
scope.todos = scope.todos.filter(function(el){
console.log("the return value for todo - " + el + " is " + (el != attr.skDel))
return el != attr.skDel
})
console.log("new set of todos ----" + JSON.stringify(scope.todos))
scope.$apply()
})
}
}
})
Console logs, 控制台日志
the return value for todo - eat is false
the return value for todo - pray is true
the return value for todo - live is true
new set of todos ---- ["pray","live"]
The problem is you are assigning a new object to todos
问题是您要向
todos
分配一个新对象
var app = angular.module('my-app', [], function() {}) app.controller('todoCtrl', function($scope, $element) { $scope.obj = { todos: ["eat", "pray", "live"] } }) app.directive("skDel", function() { return { scope: { todos: '=' }, link: function(scope, elem, attr) { elem.bind("click", function() { scope.todos = scope.todos.filter(function(el) { console.log("the return value for todo - " + el + " is " + (el != attr.skDel)) return el != attr.skDel }) console.log("new set of todos ----" + JSON.stringify(scope.todos)) scope.$apply() }) } } })
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" /> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="my-app"> <div ng-controller="todoCtrl"> <ul> <li ng-repeat="todo in obj.todos"><i class="fa fa-trash-o fa-lg" sk-del="{{todo}}" todos="obj.todos"></i>{{todo}}</li> </ul> <pre>{{todos | json}}</pre> </div> </div>
scope.todos = scope.todos.filter()
.filter
creates a new array, hence scope.todos
is pointing to the new array instead of pointing to the parent scope (Controller) scope.todos
. .filter
创建一个新数组,因此scope.todos
指向新数组,而不是指向父范围(Controller) scope.todos
。 And your view is still listening to the parent (controller) scope
, hence the view is not getting updated. 而且您的视图仍在侦听父(控制器)
scope
,因此该视图未得到更新。
However you can use .splice
, which won't change the reference of the child scope. 但是,您可以使用
.splice
,它不会更改子作用域的引用。 And thus when you update the child scope, parent $scope.todos
also get's updated, because of two way binding between parent & child. 因此,当您更新子范围时,由于父子之间的两种方式绑定,父
$scope.todos
也将得到更新。
Add $index to the ngRepeat directive. 将$ index添加到ngRepeat指令。
<li ng-repeat="todo in todos track by $index">
<i class="fa fa-trash-o fa-lg" sk-del="{{todo}}" todos="todos" index={{$index}}></i>{{todo}}
</li>
And you directive bind handlder should be as below. 并且您指令绑定handlder应该如下。
elem.bind("click", function(){
scope.todos.splice(attr.index,1);
scope.$apply();
});
The main issue is that 'false' is still a value, and will still return output on the view. 主要问题是'false'仍然是一个值,并且仍将在视图上返回输出。 Possibly an alternative to
array.filter
is array.splice
which will simply remove the item from the array. array.filter
可能是array.splice
的替代方法,它只会从数组中删除该项目。
I've created a fiddle demonstrating this: 我创建了一个小提琴来演示这一点:
http://jsfiddle.net/spanndemic/79cqxxby/ http://jsfiddle.net/spanndemic/79cqxxby/
Relevant change is to this part of the code: 相关的更改是此部分代码:
html: HTML:
<div ng-app="app">
<div ng-controller="todoCtrl">
<ul>
<li ng-repeat="todo in todos">
<i class="fa fa-trash-o fa-lg" sk-del="{{todo}}" todos="todos" data-index="{{$index}}"></i>{{todo}}
</li>
</ul>
</div>
</div>
js: JS:
var app = angular.module('app', [])
.controller('todoCtrl', function ($scope, $element) {
$scope.todos = ["eat", "pray", "live"]
})
app.directive("skDel", function(){
return {
scope:{
todos: '='
},
link: function(scope, elem, attr){
elem.bind("click", function(){
scope.todos.splice(attr.index, 1);
console.log("new set of todos ----" + JSON.stringify(scope.todos));
scope.$apply();
})
}
}
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.