AngularJS:在ng-repeat生成的范围中设置变量

时间:2021-07-25 23:12:31

How do I access the set of scopes generated by an ng-repeat?

如何访问ng-repeat生成的范围集?

I suppose at the heart of this is the fact that I don't understand quite how the relationship works between a) the collection of objects that I pass into the ng-repeat directive and b) the collection of scopes that it generates. I can play around with (a), which the ng-repeat scope watches and picks up, but how do I set variables on the scope itself (b)?

我认为这个问题的核心是我不明白这种关系如何在a)传递给ng-repeat指令的对象集合和b)它生成的作用域集合之间起作用。我可以玩(a),ng-repeat范围观察和拾取,但我如何设置范围本身的变量(b)?

My use case is that I have a set of elements repeating using ng-repeat, each of which has an edit view that gets toggled using ng-show/ng-hide; the state for each element is held in a variable in the local scope. I want to be able to trigger an ng-show on a particular element, but I want the trigger to be called from outside the ng-repeat, so I need to be able to access the local scope variable.

我的用例是我有一组使用ng-repeat重复的元素,每个元素都有一个使用ng-show / ng-hide切换的编辑视图;每个元素的状态保存在本地范围的变量中。我希望能够在特定元素上触发ng-show,但我希望从ng-repeat外部调用触发器,因此我需要能够访问本地范围变量。

Can anyone point me in the right direction (or tell me if I'm barking up the wrong tree)?

任何人都可以指出我正确的方向(或告诉我,如果我正在吠叫错误的树)?

Thanks

谢谢

Update: Link below was very helpful thankful. In the end I created a directive for each of the repeating elements, and used the directive's link function to add its scope to a collection on the root scope.

更新:下面的链接非常有用,谢天谢地。最后,我为每个重复元素创建了一个指令,并使用该指令的link函数将其作用域添加到根作用域的集合中。

3 个解决方案

#1


1  

When working within a hierarchy of scopes I find very useful to dispatch events with $emit and $broadcast. $emit dispatches an event upwards so your child scopes can notify parent scopes of a particular event. $broadcast is the other way round.

在范围的层次结构中工作时,我发现用$ emit和$ broadcast调度事件非常有用。 $ emit将向上调度一个事件,以便您的子范围可以通知特定事件的父范围。 $ broadcast是另一回事。

Alternatively, as child scopes have access to parent scope properties you could trigger changes by using $watch on a particular property in the parent scope.

或者,由于子作用域可以访问父作用域属性,因此可以通过对父作用域中的特定属性使用$ watch来触发更改。

UPDATE: As for accessing the child scopes, this may turn useful for you : Get to get all child scopes in Angularjs given the parent scope

更新:至于访问子范围,这可能对您有用:获取在父范围内获取Angularjs中的所有子范围

#2


16  

Here is a pretty simple way to do what I think you are trying to do (I figured this out when I needed to do something similar):

这是一个非常简单的方法来做我认为你想做的事情(当我需要做类似的事情时我想出了这个):

We know that each repeated item has it's own scope created for it. If we could pass this scope to a method defined on the parent scope, then we'd be able to do what we want with it in terms of manipulating or adding properties. It turn out this can be done by passing this as an argument:

我们知道每个重复的项目都有自己的范围。如果我们可以将此范围传递给父范围上定义的方法,那么我们就能够在操作或添加属性方面做到我们想要的。事实证明,这可以通过将其作为参数传递来完成:

Example

// collection on controller scope
$scope.myCollection = [
  { name: 'John', age: 25 },
  { name: 'Barry', age: 43 },
  { name: 'Kim', age: 26 },
  { name: 'Susan', age: 51 },
  { name: 'Fritz', age: 19 }
];



// template view
<ul>
  <li ng-repeat="person in myCollection">
    <span ng-class="{ bold : isBold }">{{ person.name }} is aged {{ person.age }} </span>
    <button class="btn btn-default btn-xs" ng-click="toggleBold(this)">toggle bold</button>
  </li>
</ul>

So when we press the "toggle bold" button, we are calling the $scope.toggleBold() method that we need to define on the controller's $scope. Notice that we pass this as the argument, which is actually the current ng-repeat scope object.

因此,当我们按下“toggle bold”按钮时,我们调用$ scope.toggleBold()方法,我们需要在控制器的$ scope上定义它。请注意,我们将此作为参数传递,该参数实际上是当前的ng-repeat范围对象。

Therefore we can manipulate it like this

因此我们可以像这样操纵它

$scope.toggleBold = function(repeatScope) {
  if (repeatScope.isBold) {
    repeatScope.isBold = false;
  } else {
    repeatScope.isBold = true;
  }
};

Here is a working example: http://plnkr.co/edit/Vg9ipoEP6wxG8M1kpiW3?p=preview

这是一个工作示例:http://plnkr.co/edit/Vg9ipoEP6wxG8M1kpiW3?p = preview

#3


10  

Ben Nadel has given a pretty clean solution to the "how do I assign to an ngRepeat's $scope" problem, which I just implemented in my own project. Essentially, you can add an ngController directive alongside your ngRepeat, and manipulate ngRepeat's $scope inside the controller.

Ben Nadel为“我如何分配到ngRepeat的$ scope”问题提供了一个非常干净的解决方案,我刚刚在我自己的项目中实现了这个问题。基本上,您可以在ngRepeat旁边添加ngController指令,并在控制器内操作ngRepeat的$ scope。

Below is my own contrived example, which demonstrates assigning to ngRepeat's $scope in a controller. Yes, there are better ways to do this exact thing. See Ben Nadel's post for a better example.

下面是我自己设计的例子,它演示了如何在控制器中分配ngRepeat的$ scope。是的,有更好的方法可以做到这一点。有关更好的例子,请参阅Ben Nadel的帖子。

<div ng-controller="ListCtrl">
  <h1>ngRepeat + ngController</h1>
  <ul>
    <li ng-repeat="item in items" ng-controller="ItemCtrl" ng-show="isVisible">
      {{item.name}}
      <button ng-click="hide()">hide me!</button>
    </li>
  </ul>
</div>

<script type="text/javascript">
  var app = angular.module("myApp", []);

  app.controller("ListCtrl", function($scope) {
    $scope.items = [
      {name: "Item 1"},
      {name: "Item 2"},
      {name: "Item 3"}
    ];
  });

  app.controller("ItemCtrl", function($scope) {
    $scope.isVisible = true;
    $scope.hide = function() {
      $scope.isVisible = false;
    };
  });
</script>

EDIT: Having re-read your question, seeing that you need to manipulate a bunch of child scopes in a parent scope, I think that your directive(s) approach is the way to go. I still think this answer may be useful to some, as I came across your question while looking for this answer.

编辑:重新阅读您的问题,看到您需要在父作用域中操作一堆子作用域,我认为您的指令方法是可行的方法。我仍然认为这个答案可能对某些人有用,因为我在寻找这个答案时遇到了你的问题。

#1


1  

When working within a hierarchy of scopes I find very useful to dispatch events with $emit and $broadcast. $emit dispatches an event upwards so your child scopes can notify parent scopes of a particular event. $broadcast is the other way round.

在范围的层次结构中工作时,我发现用$ emit和$ broadcast调度事件非常有用。 $ emit将向上调度一个事件,以便您的子范围可以通知特定事件的父范围。 $ broadcast是另一回事。

Alternatively, as child scopes have access to parent scope properties you could trigger changes by using $watch on a particular property in the parent scope.

或者,由于子作用域可以访问父作用域属性,因此可以通过对父作用域中的特定属性使用$ watch来触发更改。

UPDATE: As for accessing the child scopes, this may turn useful for you : Get to get all child scopes in Angularjs given the parent scope

更新:至于访问子范围,这可能对您有用:获取在父范围内获取Angularjs中的所有子范围

#2


16  

Here is a pretty simple way to do what I think you are trying to do (I figured this out when I needed to do something similar):

这是一个非常简单的方法来做我认为你想做的事情(当我需要做类似的事情时我想出了这个):

We know that each repeated item has it's own scope created for it. If we could pass this scope to a method defined on the parent scope, then we'd be able to do what we want with it in terms of manipulating or adding properties. It turn out this can be done by passing this as an argument:

我们知道每个重复的项目都有自己的范围。如果我们可以将此范围传递给父范围上定义的方法,那么我们就能够在操作或添加属性方面做到我们想要的。事实证明,这可以通过将其作为参数传递来完成:

Example

// collection on controller scope
$scope.myCollection = [
  { name: 'John', age: 25 },
  { name: 'Barry', age: 43 },
  { name: 'Kim', age: 26 },
  { name: 'Susan', age: 51 },
  { name: 'Fritz', age: 19 }
];



// template view
<ul>
  <li ng-repeat="person in myCollection">
    <span ng-class="{ bold : isBold }">{{ person.name }} is aged {{ person.age }} </span>
    <button class="btn btn-default btn-xs" ng-click="toggleBold(this)">toggle bold</button>
  </li>
</ul>

So when we press the "toggle bold" button, we are calling the $scope.toggleBold() method that we need to define on the controller's $scope. Notice that we pass this as the argument, which is actually the current ng-repeat scope object.

因此,当我们按下“toggle bold”按钮时,我们调用$ scope.toggleBold()方法,我们需要在控制器的$ scope上定义它。请注意,我们将此作为参数传递,该参数实际上是当前的ng-repeat范围对象。

Therefore we can manipulate it like this

因此我们可以像这样操纵它

$scope.toggleBold = function(repeatScope) {
  if (repeatScope.isBold) {
    repeatScope.isBold = false;
  } else {
    repeatScope.isBold = true;
  }
};

Here is a working example: http://plnkr.co/edit/Vg9ipoEP6wxG8M1kpiW3?p=preview

这是一个工作示例:http://plnkr.co/edit/Vg9ipoEP6wxG8M1kpiW3?p = preview

#3


10  

Ben Nadel has given a pretty clean solution to the "how do I assign to an ngRepeat's $scope" problem, which I just implemented in my own project. Essentially, you can add an ngController directive alongside your ngRepeat, and manipulate ngRepeat's $scope inside the controller.

Ben Nadel为“我如何分配到ngRepeat的$ scope”问题提供了一个非常干净的解决方案,我刚刚在我自己的项目中实现了这个问题。基本上,您可以在ngRepeat旁边添加ngController指令,并在控制器内操作ngRepeat的$ scope。

Below is my own contrived example, which demonstrates assigning to ngRepeat's $scope in a controller. Yes, there are better ways to do this exact thing. See Ben Nadel's post for a better example.

下面是我自己设计的例子,它演示了如何在控制器中分配ngRepeat的$ scope。是的,有更好的方法可以做到这一点。有关更好的例子,请参阅Ben Nadel的帖子。

<div ng-controller="ListCtrl">
  <h1>ngRepeat + ngController</h1>
  <ul>
    <li ng-repeat="item in items" ng-controller="ItemCtrl" ng-show="isVisible">
      {{item.name}}
      <button ng-click="hide()">hide me!</button>
    </li>
  </ul>
</div>

<script type="text/javascript">
  var app = angular.module("myApp", []);

  app.controller("ListCtrl", function($scope) {
    $scope.items = [
      {name: "Item 1"},
      {name: "Item 2"},
      {name: "Item 3"}
    ];
  });

  app.controller("ItemCtrl", function($scope) {
    $scope.isVisible = true;
    $scope.hide = function() {
      $scope.isVisible = false;
    };
  });
</script>

EDIT: Having re-read your question, seeing that you need to manipulate a bunch of child scopes in a parent scope, I think that your directive(s) approach is the way to go. I still think this answer may be useful to some, as I came across your question while looking for this answer.

编辑:重新阅读您的问题,看到您需要在父作用域中操作一堆子作用域,我认为您的指令方法是可行的方法。我仍然认为这个答案可能对某些人有用,因为我在寻找这个答案时遇到了你的问题。