简体   繁体   English

指令的绑定函数的范围更改未反映

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM