【问题标题】:AngularJS: Setting a variable in a ng-repeat generated scopeAngularJS:在 ng-repeat 生成的范围内设置变量
【发布时间】:2013-07-23 15:03:13
【问题描述】:

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

我想这个问题的核心是我不太了解 a) 我传递给 ng-repeat 指令的对象集合和 b) 它生成的范围集合之间的关系是如何工作的.我可以玩 (a),ng-repeat 范围会监视和接收它,但是如何在范围本身上设置变量 (b)?

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

谁能指出我正确的方向(或者告诉我我是不是找错了树)?

谢谢

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

【问题讨论】:

  • 在 ng-repeat 期间创建的所有作用域都继承自父作用域,因此您可以轻松地从子作用域访问父作用域元素,但不能从子作用域更改父作用域元素(适用于原始类型)。请通过这个github.com/angular/angular.js/wiki/Understanding-Scopes
  • 谢谢 - 会看看。我的问题不是我想从子作用域访问父作用域,而是反过来。
  • 您好,谢谢。我以前确实读过。我的问题不在于我不认为的继承,而是相反。如何从父级内部访问子变量?
  • 我们您可以查看scope.$broadcast 来实现您的目标。

标签: angularjs angularjs-scope angularjs-ng-repeat


【解决方案1】:

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

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

更新:至于访问子作用域,这可能对您有用:Get to get all child scopes in Angularjs given the parent scope

【讨论】:

  • 问题是,父作用域只与 ng-repeat 集合中的一个特定子作用域对话......所以不确定这将如何与 $broadcast 一起工作?对我来说最简单的解决方案就是直接在子作用域上设置一个变量,这样它就可以做一些事情......有点像 $scope.ngRepeatScopesCollection[index].var = y 但是没有这样的集合吗?或者我是在问愚蠢的问题/太多的新手来理解角度方式吗? ;-)
  • 在这种情况下,您可以将 ng-repeat 元素设置为可见,具体取决于使用 ng-class 在子作用域中注入的单个对象的特定属性。 IE。如果对象的属性 x 等于 true,则可以将元素设置为可见。看看这个 [docs.angularjs.org/api/ng.directive:ngClass]
  • 我已经在使用基于从父作用域继承的属性的 ng-class,我发现这很简单。我现在的问题是我需要在 ng-repeat 中的 particular 元素上触发 ng-show(在本例中是第一个)。
  • 目前我能看到的唯一方法是在控制器(或服务)中创建另一个集合,ng-repeat 范围在创建时会自行注册。然后我可以通过这个数组访问它们。但是,当 ngRepeat 范围在其父范围内已经(可能)有一个集合时,这似乎很疯狂?
  • 那么在这种情况下,我认为您需要看看这个 [stackoverflow.com/questions/12649080/…
【解决方案2】:

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

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

示例

// 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>

所以当我们按下“切换粗体”按钮时,我们正在调用我们需要在控制器的 $scope 上定义的$scope.toggleBold() 方法。请注意,我们将 this 作为参数传递,这实际上是当前的 ng-repeat scope 对象。

因此我们可以这样操作它

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

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

【讨论】:

  • 酷!我想知道为什么AngularJS官方网站上没有关于ng-repeat范围的“this”的信息。
【解决方案3】:

Ben Nadel 已将a pretty clean solution 提供给“我如何分配给ngRepeat$scope”问题,这是我刚刚在自己的项目中实现的。本质上,您可以在您的ngRepeat 旁边添加一个ngController 指令,并在控制器内操作ngRepeat$scope

下面是我自己设计的示例,它演示了在控制器中分配给ngRepeat$scope。是的,更好的方法来做这件事。请参阅Ben Nadel's post 以获得更好的示例。

<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>

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

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 2016-11-28
    • 2016-11-09
    • 2013-10-09
    • 1970-01-01
    • 2017-11-03
    相关资源
    最近更新 更多