Ng-click在ng-repeat中不起作用

时间:2013-05-24 14:01:11

标签: angularjs angularjs-ng-repeat angularjs-ng-click

Ng-click在ng-repeat内部不起作用。外面有效。 我放了fiddle here

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

8 个答案:

答案 0 :(得分: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;">...

Click to see a working version of your Fiddle using the $parent solution.

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

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

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

Click to see a working version of your Fiddle using the better method

答案 1 :(得分:14)

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

答案 2 :(得分: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创建新范围,您可以使用$parentng-repeat块内访问父范围。

答案 3 :(得分: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/

进行测试

答案 4 :(得分: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>

答案 5 :(得分: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:点击它开始工作,我还没找到原因,只是快速发布分享。

答案 6 :(得分:0)

我长时间在网上浏览,寻找ng-repeat在其中创建自己范围的问题的答案。在ng-repeat中更改变量时,视图不会更新文档中的其他位置。

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

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

所以

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

答案 7 :(得分:-1)

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

检查控制器上的angularjs上的documentation

对于上述问题:

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

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