27

ng-click 在 ng-repeat 内部不起作用。在外面它工作。我在这里放了一个小提琴

<div ng-controller="MyCtrl">
 <a ng-click="triggerTitle='This works!'">test</a>
    <h5>Please select trigger event: [{{triggerEvent}}] {{triggerTitle}}</h5>
       <ul class="dropdown-menu">
         <li ng-repeat="e in events">
             <a ng-click="triggerTitle=e.name; triggerEvent = e.action;">{{e.action}} - {{e.name}}</a>
         </li>
       </ul>
</div>
4

8 回答 8

52

正如 Ven 提到的,ng-repeat确实为循环中的每个项目创建了一个子范围。子作用域确实可以通过原型继承访问父作用域的变量和方法。令人困惑的部分是当您进行分配时,它会向子范围添加一个新变量,而不是更新父范围上的属性。在ng-click中,当您进行赋值调用时tiggerTitle =e.name,它实际上添加了一个新变量,称为triggerTitle子范围。AngularJS 文档在此处称为JavaScript Prototypal Inheritance的部分中很好地解释了这一点。

那么如何解决这个问题并正确设置模型变量呢?

一个快速而肮脏的解决方案是像这样访问父范围$parent

<a ng:click="$parent.triggerTitle=e.name; $parent.triggerEvent = e.action;">...

单击以查看使用 $parent 解决方案的 Fiddle 的工作版本。

$parent如果您正在处理嵌套模板或嵌套 ng-repeats,则使用可能会导致问题。更好的解决方案可能是向控制器的作用域添加一个函数,该函数返回对控制器作用域的引用。如前所述,子作用域有权调用父函数,因此可以引用控制器的作用域。

function MyCtrl($scope) {
    $scope.getMyCtrlScope = function() {
         return $scope;   
    }
 ...

<a ng-click="getMyCtrlScope().triggerTitle=e.name;getMyCtrlScope().triggerEvent = ...

单击以查看使用更好方法的 Fiddle 的工作版本

于 2014-09-25T15:30:05.683 回答
12

因为ng-repeat创建了一个新的范围。

这已经回答了很多次,因为细微差别有点难以理解,特别是如果你不了解 js 原型继承的一切:https ://github.com/angular/angular.js/wiki/Understanding-Scopes

编辑:看来这个答案很有争议。需要明确一点——这就是 JS 的工作方式。在了解 JS 的工作原理之前,您真的不应该尝试学习 Angular。但是,链接似乎确实错过了

因此,这里有一个关于 JS 在这种情况下如何工作的示例:

var a = {value: 5};
var b = Object.create(a); // create an object that has `a` as its prototype

// we can access `value` through JS' the prototype chain
alert(b.value); // prints 5
// however, we can't *change* that value, because assignment is always on the designated object
b.value = 10;
alert(b.value); // this will print 10...
alert(a.value); // ... but this will print 5!

那么,我们该如何解决呢?

好吧,我们可以“强迫”自己通过继承链——因此我们将确保我们总是访问正确的对象,无论是访问值还是修改它。

var a = {obj: {value: 5}};
var b = Object.create(a); // create an object that has `a` as its prototype

// we can access `value` through JS' the prototype chain:
alert(b.obj.value); // prints 5
// and if we need to change it,
// we'll just go through the prototype chain again:
b.obj.value = 10;
// and actually refer to the same object!

alert(b.obj.value == a.obj.value); // this will print true
于 2013-05-24T14:03:02.977 回答
6

而不是这个:

<li ng-repeat="e in events">
  <a ng-click="triggerTitle=e.name; triggerEvent = e.action;">{{e.action}} {{e.name}}</a>
</li>

只需这样做:

<li ng-repeat="e in events">
  <a ng-click="$parent.triggerTitle=e.name; $parent.triggerEvent = e.action;">{{e.action}} {{e.name}}</a>
</li>

ng-repeat创建一个新范围,您可以使用$parent它从块内部访问父范围ng-repeat

于 2015-08-26T11:54:19.353 回答
3

在这里我们可以使用 $parent 以便我们可以访问 ng-repeat 之外的代码。

html代码

<div ng-controller="MyCtrl">
        <a ng-click="triggerTitle='This works!'">test</a>


        <h5>Please select trigger event: [{{triggerEvent}}] {{triggerTitle}}</h5>
<br /> <br />
          <ul class="dropdown-menu">
            <li ng-repeat="e in events">
                <a ng-click="$parent.triggerTitle=e.name; $parent.triggerEvent = e.action;">{{e.action}} - {{e.name}}</a>
            </li>
          </ul>

Angular Js 代码

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
$scope.triggerTitle = 'Select Event';
$scope.triggerEvent = 'x';
$scope.triggerPeriod = 'Select Period';
$scope.events =  [{action:'compare', name:'Makes a policy comparison'}, {action:'purchase', name:'Makes a purchase'},{action:'addToCart', name:'Added a product to the cart'}]

}

你可以在这里测试它http://jsfiddle.net/xVZEX/96/

于 2016-10-15T11:18:24.077 回答
1

我在互联网上冲浪了很长时间,寻找 ng-repeat 在其中创建自己的范围的问题的答案。当您更改 ng-repeat 中的变量时,视图不会在文档中的其他任何地方更新。

最后我找到的解决方案是一个词,没有人告诉你。

这是$父级。在变量名之前,它将在全局范围内更改其值。

所以

ng-click="entryID=1"
变成
ng-click="$parent.entryID=1"

于 2018-05-29T21:01:55.100 回答
1

这个作品

<body ng-app="demo" ng-controller="MainCtrl">
 <ul>
    <li ng-repeat="action in actions" ng-click="action.action()">{{action.name}}</li>
 </ul>

 <script>
  angular.module('demo', ['ngRoute']);

  var demo = angular.module('demo').controller('MainCtrl', function ($scope) {
  $scope.actions = [
    { action: function () {
        $scope.testabc();
      }, name: 'foo'
    },
    { action: function () {
        $scope.testxyz();
      }, name: 'bar'
    }
  ];

  $scope.testabc = function(){
    alert("ABC");
  };

  $scope.testxyz = function(){
    alert("XYZ");
  };

 });
</script>
</body>
于 2015-10-25T16:21:34.423 回答
0

用这个

<div ng:controller="MyCtrl">
 <a ng:click="triggerTitle='This works!'">test</a>
    <h5>Please select trigger event: [{{triggerEvent}}] {{triggerTitle}}</h5>
       <ul class="dropdown-menu">
         <li ng:repeat="e in events">
             <a ng:click="triggerTitle=e.name; triggerEvent = e.action;">{{e.action}} -     {{e.name}}</a>
         </li>
       </ul>
</div>

我将 ng-click 转换为 ng:click 并开始工作,我还没有找到原因,只是快速发布分享。

于 2013-08-27T15:42:12.690 回答
-1

使用带有“as”关键字的控制器。

检查控制器上有关 angularjs的文档。

对于上述问题:

<div ng-controller="MyCtrl as myCntrl">
 <a ng-click="myCntrl.triggerTitle='This works!'">test</a>
    <h5>Please select trigger event: [{{myCntrl.triggerEvent}}] {{myCntrl.triggerTitle}}</h5>
       <ul class="dropdown-menu">
         <li ng-repeat="e in myCntrl.events">
             <a ng-click="myCntrl.triggerTitle=e.name; myCntrl.triggerEvent = e.action;">{{e.action}} - {{e.name}}</a>
         </li>
       </ul>
</div>

这会将属性和功能附加到控制器的范围内。

于 2015-03-25T13:33:05.077 回答