Javascript AngularJs指令:如何在ng repeat元素上动态设置属性

Javascript AngularJs指令:如何在ng repeat元素上动态设置属性,javascript,jquery,angularjs,jqlite,Javascript,Jquery,Angularjs,Jqlite,我对AngularJS比较陌生。在冒险创建指令时,我可以解决这个问题:当使用“ng repeat”动态添加指令元素的子元素时,如何动态添加/删除这些子元素的属性? 首先,我想到了这个解决方案: 模板 ... a.list-group-item(ng-repeat='playlist in playlists', ng-click='addToPlaylist(playlist, track)', ng-href='playlist/{{ playlist._id }}) ... link: f

我对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;
  }
... 
*指令

...
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?真:假

然后在模板中

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

虽然它很好用,但显然一点也不干燥。救命啊

你尝试做事的方式可能不是最有条理的(条条框框主义者?条条框框主义者?)。在这里尝试使用
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;
    }
  });
}
但是,这在您的情况下不太可能起作用,因为。如果你想避免你已经拥有的解决方案(我认为这比你第一次尝试要好),你必须重新实现你的代码

我建议定义一个额外的指令,使用指令定义对象的
require
属性。新指令将有权访问父指令的
add
属性(
this.add
在父指令的控制器中),并可编程为相应的行为。该解决方案的实施超出了本答案的范围

更新: 我决定给实现一个机会。该示例非常简化,但它完成了您正在尝试做的事情:根据传递给它的属性更改指令的模板。参见示例

该示例在Angular 1中使用了一个新功能:。您可以阅读有关可注入模板和组件的更多信息。基本上,组件允许您使用具有元素及其属性访问权限的函数定义模板,如下所示:

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
      };
    }]
  });
app.component('playlipcomponent'{
//我们可以将out template定义为返回字符串的函数:
模板:函数($element,$attrs){
var action=$attrs中的“添加”
“ng click=“$ctrl.addToPlaylist(播放列表,曲目)””
:'ng href=“playlist/{{playlist.\u id}}';
返回“”;
},
//组件总是使用控制器而不是作用域
控制器:[“播放列表服务”,功能(播放列表){
this.playlists=播放列表;
this.addToPlaylist=函数(播放列表、曲目){
//一些逻辑
};
}]
});

更改单击处理程序,而不是删除属性

$event
添加到参数列表中,并有条件地使用
preventDefault()

不添加时,函数返回并获取href。否则,将阻止默认设置,单击处理程序将执行添加操作

从文档中:

$event 类似于
ngClick
ngFocus
的指令在该表达式的范围内公开
$event
对象。该对象是存在jQuery时的实例或类似的jqLite对象


--

您的最终解决方案实际上并没有那么糟糕,尽管它似乎是重复的。解释没有意义。Angular在dom准备就绪之前不会引导,除非元素存在,否则指令无法激发。对
ready
如何工作的理解是不准确的。作为子元素重复元素是不同的situation@charlietfl您是否能够编辑答案以更正它,或者提供更好的答案?我可能措辞不准确,但我认为解决办法会奏效。我会尝试重新措辞,但如果我仍然没有弄清楚,请随意编辑。整个问题似乎是“先鸡后蛋”。在第一个循环中循环重复的dom节点毫无意义place@charlietfl好的,我同意。这就是为什么我建议了一个替代方案,尽管这需要一个完全不同的实现。但是我不认为在编译属性之后,删除
ng click
属性仍然有效。。。不会删除Element上的事件侦听器非常感谢此解决方案。它就像一个符咒,干巴巴地解决问题。谢谢不仅溶液是干的。它解决了您的问题,而无需编写自定义指令。您可以使用内置指令实现您想要的。谢谢你的投票。