我正在使用 AngularJS 开发一个小解决方案(我是新手),我正在尝试使用 <dl> <dt> <dd>
创建一个 Accordion 效果标签。我定义了一个 ng-repeat
从 .json 文件在 dl 中创建 dt 和 dd,效果很好。
当我想通过指令添加一些功能时,我的问题出现了,所以我可以显示/隐藏 <dd>
单击 <dt>
元素元素。我的指令代码似乎无法正常工作,因为它并没有真正按照我的预期执行 - 它什么也没做 -。 也许 该指令尝试在 ng-repeat
之前添加功能已经完成它的过程?但为此我添加了 $timeout 变量。
整个解决方案:http://codepen.io/valecarlos/pen/PNdpeZ
指令代码:
app.directive('accordion', function($timeout){
return{
restrict: 'E',
transclude: true,
replace: true,
scope: {},
template: '<dl ng-transclude></dl>',
link: function(scope,element){
$timeout(function() {
console.log(element)
console.log(element.children().length);//this gives me 0
console.log("im here" + element)
element.children().find('dd').css('display','none');
element.find('dt').on('click', function(event){
element.children().find("dd").css('display', 'none')
var ddToOpen = angular.element(event.target).next();
ddToOpen.css('display','block');
});
});
}
};
});
HTML:
<accordion>
<dt ng-repeat-start="article in articles">
//my content
</dt>
<dd ng-repeat-end="">
//my content
</dd>
<accordion>
注意:我尝试使用 jquery 和 AngularJS 来实现这个 Accordion ,但是当我点击 dt
时什么也没有发生。元素
最佳答案
问题是(如笔中所示)您正在异步加载数据,而不是等待 promise 解决。这就是我的意思:
$http.get('http://www.carlosvalencia.co/news_mock.json').success(function(data) {
//$timeout and the DOM stuff will be long gone when we get here :(
$scope.articles = data;
});
当然,使用 $timeout
会等到 Angular 完成其模板渲染工作,但它不会等待您的数据加载。 DOM 操作完成后,没有要列出的文章,因此也没有要查找的元素。
现在您需要做的是以某种方式告诉您的指令在数据准备好之前延迟执行它的操作。我没有明确的通用解决方案来执行此操作。 Angular 为组件之间的通信提供了多种方法,它们都可以很好地用于某些目的,但可能不适用于其他目的。例如,这里最简单的做法可能就是使用 scope.$broadcast告诉指令一切就绪。
不过,这可能不是最好的解决方案,因为事件会在组件之间创建非常微妙的依赖关系。相反,我会在 Accordion 指令中明确要求 promise ,以便父 Controller 可以指示我们何时准备好滚动。所以我要补充
scope: {
promise: '&?' //Ask for an optional promise getter from the parent template
}
template: '<dl ng-transclude></dl>',
link: function(scope,element){
//We'll either wait for the given promise or default to a resolved promise
var promise = scope.promise ? scope.promise() : $q.resolve();
//Wait for both that promise AND the additional $timeout before doing DOM stuff
promise.then($timeout).then(function() {
console.log(element)
console.log(element.children().length);//shouldn't be 0 anymore
//... the DOM stuff
});
}
现在我们只需要从父 Controller 传递 $http promise。
$scope.promise = $http.get('http://www.carlosvalencia.co/news_mock.json').success(function(data) {
$scope.articles = data;
});
并在使用 Accordion 指令时使用它
<accordion promise="promise" >
<dt ng-repeat-start="article in articles">
...
Here's a working solution .
(请注意,我必须用其他方法替换 $http
方法进行测试,您应该可以使用 $http)
更新:您还需要将所有 element.children().find(selector)
调用替换为 element.find(selector)
找到元素。我已经更新了笔以涵盖这一点。
关于javascript - 带有 ng-repeat 的 Angular JS 指令无法遍历子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36853165/