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

时间:2022-08-23 12:42:00

Ng-click doesn't work from inside ng-repeat. Outside it works. I've put a fiddle here

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>

8 个解决方案

#1


51  

As Ven mentioned, ng-repeat does create a child scope for each item in the loop. The child scopes do have access to the parent scope's variables and methods through prototypal inheritance. The confusing part is when you make an assignment, it adds a new variable to the child scope rather than updating the property on the parent scope. In ng-click, when you make an assignment call tiggerTitle =e.name, it actually adds a new variable called triggerTitle to the child scope. The AngularJS docs explains this well in the section here called JavaScript Prototypal Inheritance.

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

So how do you get around this and set the model variable properly?

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

A quick and dirty solution is to access the parent scope using $parent like so.

一个快速而肮脏的解决方案是使用$ 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.

点击查看使用$ parent解决方案的小提琴的工作版本。

The use of $parent can cause issues if you are dealing with nested templates or nested ng-repeats. A better solution may be to add a function to the controller's scope which returns a reference to the controller's scope. As already mentioned, the child scopes have access to call the parent functions, and thus can reference the controller's scope.

如果您正在处理嵌套模板或嵌套的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

单击以使用更好的方法查看您的小提琴的工作版本

#2


14  

Because ng-repeat creates a new scope.

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

This has been answered numerous time, because the nuance is a bit difficult to understand, especially if you don't know everything about js's prototypal inheritance : https://github.com/angular/angular.js/wiki/Understanding-Scopes

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

EDIT: it seems this answer is very controversial. Just to be clear – this is how JS works. You really shouldn't try to learn Angular before understand how JS works. However, the link does seem to miss

编辑:似乎这个答案很有争议。要清楚 - 这就是JS的工作方式。在了解JS如何工作之前,你真的不应该尝试学习Angular。但是,链接确实似乎错过了

So, here's an example on how JS works in this case:

所以,这是一个关于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!

So, how can we work around that?

那么,我们如何解决这个问题呢?

Well, we can "force" ourselves to go through the inheritance chain – and thus we'll be sure we're always accessing the correct object, whether accessing value or modifying it.

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

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

#3


6  

Instead of this:

而不是这个:

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

Just do this:

这样做:

<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 creates a new scope, you can use $parent to access the parent scope from inside the ng-repeat block.

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

#4


3  

Here we can use $parent so that we can access the code outside of the ng-repeat.

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

Html code

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 code

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'}]

}

}

you can test it here http://jsfiddle.net/xVZEX/96/

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

#5


1  

This Works

这个作品

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

#6


0  

use this

用这个

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

I converted ng-click to ng:click and it started working, I am yet to find the reason, just quickly posted to share.

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

#7


0  

I surfed the internet for so long looking for an answer to the problem of ng-repeat creating its own scope within it. When you change a variable inside ng-repeat, the views don't update everywhere else in the document.

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

And finally the solution I found was one word, and no one tells you that.

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

It's $parent. before the variable name and it will change its value in the global scope.

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

So

所以

ng-click="entryID=1"
becomes
ng-click="$parent.entryID=1"

ng-click =“entryID = 1”变为ng-click =“$ parent.entryID = 1”

#8


-1  

Use controllers with the 'as' keyword.

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

Check the documentation on angularjs on controllers.

查看控制器上angularjs的文档。

For the above question:

对于上述问题:

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

This will attach the properties and functions to the scope of the controller.

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

#1


51  

As Ven mentioned, ng-repeat does create a child scope for each item in the loop. The child scopes do have access to the parent scope's variables and methods through prototypal inheritance. The confusing part is when you make an assignment, it adds a new variable to the child scope rather than updating the property on the parent scope. In ng-click, when you make an assignment call tiggerTitle =e.name, it actually adds a new variable called triggerTitle to the child scope. The AngularJS docs explains this well in the section here called JavaScript Prototypal Inheritance.

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

So how do you get around this and set the model variable properly?

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

A quick and dirty solution is to access the parent scope using $parent like so.

一个快速而肮脏的解决方案是使用$ 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.

点击查看使用$ parent解决方案的小提琴的工作版本。

The use of $parent can cause issues if you are dealing with nested templates or nested ng-repeats. A better solution may be to add a function to the controller's scope which returns a reference to the controller's scope. As already mentioned, the child scopes have access to call the parent functions, and thus can reference the controller's scope.

如果您正在处理嵌套模板或嵌套的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

单击以使用更好的方法查看您的小提琴的工作版本

#2


14  

Because ng-repeat creates a new scope.

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

This has been answered numerous time, because the nuance is a bit difficult to understand, especially if you don't know everything about js's prototypal inheritance : https://github.com/angular/angular.js/wiki/Understanding-Scopes

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

EDIT: it seems this answer is very controversial. Just to be clear – this is how JS works. You really shouldn't try to learn Angular before understand how JS works. However, the link does seem to miss

编辑:似乎这个答案很有争议。要清楚 - 这就是JS的工作方式。在了解JS如何工作之前,你真的不应该尝试学习Angular。但是,链接确实似乎错过了

So, here's an example on how JS works in this case:

所以,这是一个关于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!

So, how can we work around that?

那么,我们如何解决这个问题呢?

Well, we can "force" ourselves to go through the inheritance chain – and thus we'll be sure we're always accessing the correct object, whether accessing value or modifying it.

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

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

#3


6  

Instead of this:

而不是这个:

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

Just do this:

这样做:

<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 creates a new scope, you can use $parent to access the parent scope from inside the ng-repeat block.

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

#4


3  

Here we can use $parent so that we can access the code outside of the ng-repeat.

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

Html code

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 code

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'}]

}

}

you can test it here http://jsfiddle.net/xVZEX/96/

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

#5


1  

This Works

这个作品

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

#6


0  

use this

用这个

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

I converted ng-click to ng:click and it started working, I am yet to find the reason, just quickly posted to share.

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

#7


0  

I surfed the internet for so long looking for an answer to the problem of ng-repeat creating its own scope within it. When you change a variable inside ng-repeat, the views don't update everywhere else in the document.

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

And finally the solution I found was one word, and no one tells you that.

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

It's $parent. before the variable name and it will change its value in the global scope.

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

So

所以

ng-click="entryID=1"
becomes
ng-click="$parent.entryID=1"

ng-click =“entryID = 1”变为ng-click =“$ parent.entryID = 1”

#8


-1  

Use controllers with the 'as' keyword.

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

Check the documentation on angularjs on controllers.

查看控制器上angularjs的文档。

For the above question:

对于上述问题:

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

This will attach the properties and functions to the scope of the controller.

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