简体   繁体   English

对指令和父范围进行AngularJS ng-repeat

[英]AngularJS ng-repeat on directive and parent scope

I have a repeated directive which inherits the scope from it's parent controller. 我有一个重复的指令,它继承了它的父控制器的范围。

    <div ng-controller="myController">
        {{ message }}
        <person ng-repeat="person in persons"></person>
    </div>

app.controller('myController', function ($scope) {
    $scope.message = "A";
    $scope.persons = { 1: {}, 2: {}, 3: {} }
});

But when I change the scope inside the directive, the parent scope does not update. 但是当我更改指令内的范围时,父范围不会更新。

app.controller('PersonController', function ($scope) {
    $scope.message = "B";
});

app.directive("person", function () {
    return {
        restrict: 'E',
        transclude: true,
        controller: 'PersonController',
        template: '{{ message }}'
    };
});

http://jsfiddle.net/hientc/L8xo9338/1/ http://jsfiddle.net/hientc/L8xo9338/1/

This only happens when I have an ng-repeat on the directive. 只有当我对指令进行ng-repeat时才会发生这种情况。 If I remove the ng-repeat, the parent scope is updated when the directive scope is updated. 如果删除ng-repeat,则更新指令范围时会更新父作用域。

How do I make two-way binding work for ng-repeat? 如何为ng-repeat进行双向绑定工作?

Change instances of message to message.value . message实例更改为message.value

HTML: HTML:

<div ng-app="myApp">
    <div ng-controller="myController">
        {{ message.value }}
        <person ng-repeat="person in persons"></person>
    </div>
</div>

JS: JS:

// Inside myController

$scope.message = {
    value: "A"
};
// Inside PersonController
app.controller('PersonController', function ($scope) {
    $scope.message.value = "B";
});

http://jsfiddle.net/L8xo9338/2/ http://jsfiddle.net/L8xo9338/2/

This has to do with how scopes inherit using javascript's prototype . 这与范围如何使用javascript的prototype继承有关。 See What are the nuances of scope prototypal / prototypical inheritance in AngularJS? 请参阅AngularJS中范围原型/原型继承的细微差别是什么? for an explanation. 作出解释。

Essentially, when you create an object, the scopes reference the same object so it will be updated. 实质上,当您创建对象时,范围引用相同的对象,以便更新它。

This could be done alternatively with $scope.$parent.message = "B"; 这可以用$scope.$parent.message = "B";替代完成$scope.$parent.message = "B"; . However, to me it is less clean. 但是,对我来说它不太干净。

You can even bind this to a model eg <input ng-model="message.value"> and it will update in the parent and in the child. 您甚至可以将其绑定到模型,例如<input ng-model="message.value"> ,它将在父级和子级中更新。

I think your issue is related to the prototypical inheritance of JavaScript, which behaves differently when you are reading or writing members: 我认为您的问题与JavaScript的原型继承有关,当您阅读或编写成员时,它的行为会有所不同:

Your directive creates a new scope and tries to set the message member on it. 您的指令创建一个新范围并尝试在其上设置message成员。 As the member does not exist, it is created on that scope (and not, as you might think, be set on the parent scope which already has this member). 由于该成员不存在,因此它是在该作用域上创建的(而不是如您所想,可以在已具有此成员的父作用域上设置)。 This means the message member is created on the "wrong" scope (for what you are trying to do). 这意味着message成员是在“错误”范围内创建的(对于您要执行的操作)。

The write-behavior is different than the read behavior. 写行为与读行为不同。 If you are trying to access a property from a child scope on the parent scope, you will bubble up, until the property is found, otherwise it will be undefined . 如果您尝试从父作用域上的子作用域访问属性,则会冒泡,直到找到该属性,否则将是undefined

This can be solved by setting the value via a method. 这可以通过方法设置值来解决。 This method should be placed on the scope which has the member which needs to be set. 此方法应放在具有需要设置的成员的范围上。 In your case something like this should work: 在你的情况下,这样的东西应该工作:

On myController : myController

$scope.SetMessage = function(m)
{
    $scope.message = m;
}

And PersonController should be changed as follows: 并且PersonController应该更改如下:

app.controller('PersonController', function ($scope)
{
    $scope.SetMessage("B");
});

You could also access the parent scope via $scope.$parent which might work for the moment, but break as soon as you add/remove a scope (eg by nesting it in another directive). 您也可以通过$scope.$parent访问父作用域,它可能暂时可用,但只要添加/删除作用域就会中断(例如,通过将其嵌套在另一个指令中)。 Using a method is more flexibel. 使用方法更灵活。 By the way: that's why it's not working with ng-repeat , as this creates a new scope for every item. 顺便说一下:这就是为什么它没有使用ng-repeat ,因为这为每个项目创建了一个新的范围。

First of all, your person directive does NOT create any new scope, it reuses the same scope as its parent. 首先,你的person指令不会创建任何新的范围内,重复使用相同的范围是其父母。 That is why your directive works when you didn't use ng-repeat 这就是为什么你的指令在不使用ng-repeat

Second of all, ng-repeat creates new scopes . 其次, ng-repeat 创建了新的范围 According to ng-repeat document 根据ng-repeat文件

Each template instance gets its own scope, where the given loop variable is set to the current collection item 每个模板实例都有自己的范围,其中给定的循环变量设置为当前集合项

So when you use ng-repeat , even though your directive still doesn't create new scope, it is sharing a new scope created by ng-repeat . 因此,当您使用ng-repeat ,即使您的指令仍未创建新范围,它也会共享由ng-repeat创建的新范围。 That is why setting the message in your directive doesn't affect the parent scope anymore. 这就是为什么在指令中设置message不再影响父范围的原因。

Hope this helps! 希望这可以帮助! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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