Ng-click не работает внутри ng-repeat
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>
Ответы
Ответ 1
Как упоминалось в Ven, ng-repeat
создает дочернюю область для каждого элемента цикла. У дочерних областей есть доступ к переменным и методам родительской области с помощью прототипального наследования. Запутанная часть - это когда вы выполняете задание, она добавляет новую переменную в область дочерних элементов, а не обновляет свойство в родительской области. В ng-click
, когда вы делаете вызов назначения tiggerTitle =e.name
, он фактически добавляет новую переменную с именем triggerTitle
в область дочерних элементов. Документы AngularJS объясняют это хорошо в разделе, который называется Прототипное наследование JavaScript.
Итак, как вам обойти это и правильно настроить модель?
Быстрое и грязное решение заключается в доступе к родительской области с помощью $parent
.
<a ng:click="$parent.triggerTitle=e.name; $parent.triggerEvent = e.action;">...
Нажмите, чтобы увидеть рабочую версию вашего скрипта, используя $parent решение.
Использование $parent
может вызвать проблемы, если вы имеете дело с вложенными шаблонами или вложенными ng-повторами. Лучшим решением может быть добавление функции в область контроллера, которая возвращает ссылку на область управления. Как уже упоминалось, дочерние области имеют доступ к вызовам родительских функций и, следовательно, могут ссылаться на область контроллера.
function MyCtrl($scope) {
$scope.getMyCtrlScope = function() {
return $scope;
}
...
<a ng-click="getMyCtrlScope().triggerTitle=e.name;getMyCtrlScope().triggerEvent = ...
Нажмите, чтобы увидеть рабочую версию вашего скрипта, используя лучший метод
Ответ 2
Потому что ng-repeat
создает новую область.
Это ответили много раз, потому что нюанс немного сложно понять, особенно если вы не знаете все о прототипном наследовании js: https://github.com/angular/angular.js/wiki/Understanding-Scopes
EDIT: кажется, этот ответ очень спорный. Чтобы быть понятным - так работает JS. Вы действительно не должны пытаться изучить Angular, прежде чем понимать, как работает JS.
Однако ссылка, похоже, пропустит
Итак, вот пример того, как 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
Ответ 3
Вместо этого:
<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
.
Ответ 4
Здесь мы можем использовать $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/
Ответ 5
Это работает
<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
используйте этот
<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: нажмите, и он начал работать, но я еще не нашел причину, просто быстро опубликовал ее.
Ответ 7
Используйте контроллеры с ключевым словом "как".
Проверьте документацию на 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>
Это добавит свойства и функции в область действия контроллера.