对指令使用ng-repeat会导致子指令不更新

时间:2021-05-30 19:44:11

so if found this very interesting bug in angular.js. if you have a custom directive inside a ng-repeat that is actively changing the variables in the directive don't update. meaning if i have 3 elements in my array for ng-repeat it initializes just fine but if i delete element 1 from the array any variables that element 1 had passed to its child directive somehow end up in element 2's child directive here is my example code.

如果在angular。js中找到这个有趣的bug。如果在ng-repeat中有一个自定义指令正在积极地更改该指令中的变量,则不要更新该指令。也就是说,如果我的数组中有3个元素用于ng-repeat它初始化得很好但是如果我从数组中删除元素1传递给它的子指令的任何变量在元素2的子指令中以某种方式结束这是我的示例代码。

<div ng-app='testing'>
    <div ng-controller='testing as test'>
        <div ng-repeat='item in test.example track by $index'>
            {{item.title}}
            <child scope='item.data'></child>
            <button ng-click="test.delete($index)">
               Delete
            </button>
        </div>
    </div>
</div>

then in my js file

然后在我的js文件中

console.log('hello world');
var app=angular.module('testing',['testingChild']);
app.controller('testing',[function(){
    this.example=[{
        title:"this is the first title",
        data:"this is the first index"
    },{
        title:"this is the second title",
        data:"this is the second index"
    },{
        title:"this is the third title",
        data:"this is the third index"
    }];
    this.delete=function(index){
        this.example.splice(index,1);
    };
}]);
var child=angular.module('testingChild',[]);
child.directive('child',[function(){
    return{
        restrict:"E",
        scope:{
            parent:"=scope"
        },
        template:"<div>{{child.parent}}</div>",
        controller:['$scope',function($scope){
            this.parent=$scope.parent;
        }],
        controllerAs:"child"
    };
}]);

and i have a functioning jsfiddle here. all you have to do to see it work is delete one of the first elements. does anyone know what causes this and how to fix it?

我在这里有一个功能正常的jsfiddle。你所要做的就是删除第一个元素。有人知道是什么导致了这个问题吗?

Side note:

注:

I thought it might be useful also to mention that when using this in a slighty different situation with editable elements in the child (like a text box) the data binding worked from the child to the parent. so assigning a variable attached to the controller to the scoped variable from the parent worked in that direction. this seems to be the only situation i have come across where it would be from the parent to the child and that is what is not working.

我还认为有必要提一下,当在一种稍微不同的情况下使用子元素(如文本框)的可编辑元素时,数据绑定可以从子元素工作到父元素。因此,将一个附加到控制器的变量从父变量分配到作用域变量是朝着这个方向进行的。这似乎是我遇到的唯一一种情况,从父母到孩子,这是不正常的。

2 个解决方案

#1


1  

Change:

变化:

template:"<div>{{child.parent}}</div>",
controller:['$scope',function($scope){ this.parent=$scope.parent; }]

To:

:

template:"<div>{{parent}}</div>"
controller:function(){ }

since you are using controllerAs syntax, you dont need the $scope injection. For the binding work as expected, you dont use child.parent, only parent (or whatever you inject in the this context on your controller

因为您正在使用controllerAs语法,所以不需要$scope注入。对于预期的绑定工作,您不会使用child。父类,仅父类(或您在控制器的上下文中注入的任何内容)

#2


1  

I found a property in the $compile service that fixes this problem. adding the attribute bindToController:true to the directive takes all of the variables defined in your scope attribute and attaches them to the controller rather then the scope itself meaning the 2 way data binding is to the variable on the controller rather then the variable on the scope. so the end result has these changes

我在$compile服务中发现了一个属性,该属性可以修复这个问题。添加属性bindToController:true to the directive将接受作用域属性中定义的所有变量并将它们附加到控制器上,而不是作用域本身,也就是说两种数据绑定方式是针对控制器上的变量,而不是作用域上的变量。所以最终的结果有这些变化

in your directive definition

在你的指令定义

scope:{
    parent:"=scope"
},
bindToController:true,

and in the controller remove the this.parent=$scope.parent

在控制器中,删除this.parent=$scope.parent

here is an updated jsfiddle

这是一个更新的jsfiddle。

#1


1  

Change:

变化:

template:"<div>{{child.parent}}</div>",
controller:['$scope',function($scope){ this.parent=$scope.parent; }]

To:

:

template:"<div>{{parent}}</div>"
controller:function(){ }

since you are using controllerAs syntax, you dont need the $scope injection. For the binding work as expected, you dont use child.parent, only parent (or whatever you inject in the this context on your controller

因为您正在使用controllerAs语法,所以不需要$scope注入。对于预期的绑定工作,您不会使用child。父类,仅父类(或您在控制器的上下文中注入的任何内容)

#2


1  

I found a property in the $compile service that fixes this problem. adding the attribute bindToController:true to the directive takes all of the variables defined in your scope attribute and attaches them to the controller rather then the scope itself meaning the 2 way data binding is to the variable on the controller rather then the variable on the scope. so the end result has these changes

我在$compile服务中发现了一个属性,该属性可以修复这个问题。添加属性bindToController:true to the directive将接受作用域属性中定义的所有变量并将它们附加到控制器上,而不是作用域本身,也就是说两种数据绑定方式是针对控制器上的变量,而不是作用域上的变量。所以最终的结果有这些变化

in your directive definition

在你的指令定义

scope:{
    parent:"=scope"
},
bindToController:true,

and in the controller remove the this.parent=$scope.parent

在控制器中,删除this.parent=$scope.parent

here is an updated jsfiddle

这是一个更新的jsfiddle。