我对AngularJS比较陌生。冒险进入指令创建时,我可以解决这个问题:当这些孩子动态添加' ng-repeat'时,如何在指令元素的子元素上动态添加/删除属性。吗
首先,我想到了这个解决方案:
模板
...
a.list-group-item(ng-repeat='playlist in playlists', ng-click='addToPlaylist(playlist, track)', ng-href='playlist/{{ playlist._id }})
...
*指令
link: function(scope, elm, attrs) {
var listItems = angular.element(element[0].getElementsByClassName('list-group-item')
angular.forEach(listItems, function(item, index) {
'add' in attrs ? item.removeAttr('href') : item.removeAttr('ng-click');
listItems[index] = item;
}
...
结果
事实证明,我的代码永远不会进入此angular.forEach
循环,因为listItems为空。我想这是因为ng-repeat
正在等待scope.playlists通过$ resource填充从异步调用到服务器的数据。
临时修复
在指令定义中,我添加了一个布尔变量,用于检查是否存在' add'在元素的属性中:var adding = 'add' in attrs ? true : false;
然后在模板中,
a.list-group-item(ng-if='adding', ng-repeat='playlist in playlists', ng-click='addToPlaylist(playlist, track)')
a.list-group-item(ng-if='!adding', ng-repeat='playlist in playlists', ng-href='playlist/{{playlist._id }}')
虽然它运作良好,但显然不是DRY。救命!
答案 0 :(得分:2)
你尝试做事的方式可能不是最具角度的(Angularist?Angularyist?)方式。当您在此处尝试使用angular.element()
选择子元素时,您可以确保子元素已准备好,如下所示:
link: function(scope, elm, attrs) {
elm.ready(function() {
var listItems = angular.element(element[0].getElementsByClassName('list-group-item')
angular.forEach(listItems, function(item, index) {
'add' in attrs ? item.removeAttr('href') : item.removeAttr('ng-click');
listItems[index] = item;
}
});
}
但是,这不太适合您的情况,如@charlietfl points out below。如果你想避免你已经拥有的解决方案(我认为这比你的第一次尝试更好),你将不得不重新实现你的代码。
我建议使用指令定义对象的require
属性定义communicates with its parent directive的附加指令。新指令可以访问父指令({em>控制器中的父add
}的this.add
属性,并且可以编程为相应的行为。该解决方案的实施超出了这个答案的范围。
我决定给实施一些注意事项。该示例是高度简化的,但它会执行您要执行的操作:根据传递给它的属性更改指令的模板。请参阅示例here。
该示例使用Angular 1中的新功能:components。您可以阅读有关可注入模板和组件here的更多信息。从本质上讲,组件允许您使用可以访问元素及其属性的函数来定义模板,如下所示:
app.component('playlistComponent', {
// We can define out template as a function that returns a string:
template: function($element, $attrs) {
var action = 'add' in $attrs
? 'ng-click="$ctrl.addToPlaylist(playlist, track)"'
: 'ng-href="playlist/{{playlist._id}}"';
return '<a class="list-group-item" ng-repeat="playlist in playlists" ' +
action + '></a>';
},
// Components always use controllers rather than scopes
controller: ['playlistService', function(playlists) {
this.playlists = playlists;
this.addToPlaylist = function(playlist, track) {
// Some logic
};
}]
});
答案 1 :(得分:2)
不要删除属性,而是更改点击处理程序。
将$event
添加到参数列表中,并有条件地使用preventDefault()
。
<a ng-click='addToPlaylist($event,playlist)' ng-href='playlist'>CLICK ME</a>
在您的控制器中:
$scope.addToPlaylist = function(event,playlist) {
if (!$scope.adding) return;
//otherwise
event.preventDefault();
//do add operation
};
当不添加时,函数返回并获取href。否则,将阻止默认值,并且单击处理程序执行添加操作。
来自文档:
$事件
ngClick
和ngFocus
等指令在该表达式的范围内公开$event
对象。当jQuery存在或类似的jqLite对象时,该对象是jQuery Event Object的实例。