如何在自定义指令中处理 ng-repeat 子元素?
Posted
技术标签:
【中文标题】如何在自定义指令中处理 ng-repeat 子元素?【英文标题】:How can I get a handle on ng-repeat children elements in my custom directive? 【发布时间】:2013-07-26 19:28:07 【问题描述】:我正在尝试构建一个自定义指令,将其内容重新排列为网格。
我想嵌入 ng-repeat
指令的结果,然后重新排序结果元素。
问题是当我在链接函数中调用element.children()
方法时,我有一个空数组,因为ng-repeat
指令尚未呈现并被解释为注释。
否则,如果指令的内容是“静态”,则该指令效果很好。
<grid n='6'>
<div ng-repeat="i in [1,2,3]"></div>
</grid>
我的指令只有有趣的代码片段:
app.directive('grid', [function ()
return
restrict: 'E',
replace: true,
transclude: true,
template: "<div ng-transclude></div>",
link: function (scope, grid, attrs)
// With an ngRepeat transcluded, els result in an empty array
var els = grid.children();
// ...
;
]);
我错过了什么?
【问题讨论】:
在你的链接函数中你可以尝试使用 $timout(function() //access grid children,0); 确实有效,但是这种方法可靠吗? 实际上你的子模板是在发布链接功能之后渲染的,所以你需要添加$timout,它会工作,因为它会引入一些延迟。 嘿@Laurent 我的建议能以任何方式帮助你吗?请分享您的发现 @scniro:感谢您抽出宝贵时间回复。大约两年前我发布了这个问题,所以我现在继续前进,但是我相信你的回答会对其他遇到它的人有用! 【参考方案1】:要实现重新排序,您有多种选择:
-
操作 DOM。恕我直言,这是最不受欢迎的方式,它不是很棱角分明。
在您的链接函数中重新排序
ngRepeat
中使用的数组 ([1, 2, 3])。
使用orderBy
过滤器(doc)
我创建了一个 plunk 来演示 2 和 3,希望它可以提供帮助。 http://plnkr.co/edit/vrgeBoJZiG6WMu4Rk46u?p=preview
【讨论】:
我可能用“重新订购”一词误导了您。我的目标更多是将元素重新排列为网格(例如 3 个元素/行)。无论如何谢谢你;)【参考方案2】:有几种方法可以解决这个问题。您将看到的最简单和最常见的解决方案是 cmets 建议的 - 像这样利用 $timeout...
.directive('grid', ['$timeout', function ($timeout)
return
restrict: 'E',
replace: true,
transclude: true,
template: '<div ng-transclude></div>',
link: function (scope, grid, attrs)
$timeout(function()
console.log(grid.children());
);
]);
$timeout([fn], [delay], [invokeApply], [Pass]);
[...]
invokeApply
- 如果设置为 false 则跳过模型脏检查,否则将在 $apply 块中调用 fn。 (默认:true)
调用 $timeout
将强制执行 $digest
循环 - 因此,当您记录子项时 - ng-repeat
指令将“完成”。与ng-repeat
的竞争是这里问题的症结所在——因为当我们进入link
函数时,它仍在发挥作用。
您可以解决此问题的另一种方法 - 这当然不太常见 - 但在说明更详细的事件序列方面做得很好,如下...
.directive('grid', [function ()
return
restrict: 'E',
replace: true,
transclude: true,
template: '<div ng-transclude></div>',
link: function (scope, grid, attrs)
scope.$on('repeat-done', function ()
console.log(grid.children());
);
])
.directive('ngRepeat', [function ()
return
restrict: 'A',
link: function (scope, elem, attrs)
if (scope.$last)
scope.$root.$broadcast('repeat-done');
;
]);
在这里,我们悄悄地扩展 ng-repeat
以在完成时调用一个函数 - 我们可以通过 $on
在我们的 link
函数中订阅它。
JSFiddle Link - 展示这两种方法的简单演示
【讨论】:
以上是关于如何在自定义指令中处理 ng-repeat 子元素?的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS:如何使用自定义指令来取代ng-repeat
Angular 自定义指令在 ng-repeat 中使用 if 条件
如何使用 ControlValueAccessor Angular 在自定义输入中使用指令