我正在尝试使用Angular和D3创建一个类别列表。我已经为这个列表创建了一个指令,我的模板中的一些子节点使用了ng-repeat,因为我想使用角度构建我的html而不是d3。
我的问题是,当尝试用d3引用ng重复元素时,它们尚未创建。如果我使用链接功能,列表中没有项目。如果我使用编译功能,我可以看到1个列表项,但应该至少有2个。
取自小提琴:
angular.module('myApp').directive('targetingCategories', function(){
return {
restrict: 'E',
scope: {
data: '='
},
template: '<div>'+
'<ul class="catList">'+
'<li ng-repeat="cat in data.categories">'+
'{{cat.name}}'+
'<ul class="subCatList">'+
'<li ng-repeat="subcat in cat.categories">{{subcat.name}}</li>'+
'</ul>'+
'</li>'+
'</ul>'+
'</div>',
replace: true,
compile: function($tEl, $attrs){
// attach d3 on the TEMPLATE element, and look for list items
var vis = d3.select($tEl[0]);
var catList = vis.select('.catList');
var catListFirstItem = vis.select('.catlist>li');
var catListItems = vis.selectAll('.catList>li');
console.log(catList); // 1 item returned (the ul)
console.log(catListFirstItem); // 1 item returned (the first li)
console.log(catListItems); // 1 items returned ??
return function($scope, $el, $attrs){
// attach d3 to INSTANCE element and look for list items
var vis = d3.select($el[0]);
var catList = vis.select('.catList');
var catListFirstItem = vis.select('.catlist>li');
var catListItems = vis.selectAll('.catList>li');
console.log(catList); // 1 item returned (the ul)
console.log(catListFirstItem); // 1 item returned (the first li)
console.log(catListItems); // 0 items returned ??
};
}
};
});
这个想法是让角度构建我的标记,并且d3为它制作动画。我喜欢d3给我的控件与使用CSS动画的控件。
当我使用d3创建列表项时,这是working just fine。我很想再次这样做,但我认为将LI放在模板中是一个更好的架构。
我在想我需要调用编译器,或者等待一个或者什么。我几乎达到了我的角色知识的极限,所以在这里的任何教育都受到赞赏。
答案 0 :(得分:1)
我正在添加我自己的潜在答案,但是留下没有标记的任何其他人都有更好的东西。
目前,似乎实现此目的的一种方法是将主模板中的LI替换为其他嵌套指令,特别是“mainCategory”和“subCat”。然后我可以将d3附加到适当的动画实例元素。通过包含索引属性属性,我可以控制延迟以使动画交错。它感觉有点复杂和“骨干式”(对象的对象),但它解决了我的问题。它还允许我附加一些ng-clicks,这些点击是d3创建我的LI的麻烦/不可能的。
是的,我知道我的属性被称为“数据”并且可能有问题,但我现在并不担心。尽管如此,我对使用服务/控制器/指令的任何更正都表示赞赏:)
angular.module('myApp').directive('targetingCategories', function(){
return {
restrict: 'E',
scope: {
data: '='
},
template: '<div>'+
'<ul class="catList">'+
'<main-category ng-repeat="cat in data.categories" index="$index">'+
'{{cat.name}}'+
'<ul class="subCatList">'+
'<sub-cat ng-repeat="subcat in cat.categories" index="$index" data="subcat">{{subcat.name}}</sub-cat>'+
'</ul>'+
'</main-category>'+
'</ul>'+
'</div>',
replace: true
};
});
angular.module('myApp').directive('mainCategory', function(targetingService){
return {
restrict: "E",
scope: {
index: "=",
data: "="
},
template: '<li ng-transclude ng-click="selectCategory($event, data);"></li>',
replace: true,
transclude: true,
link: function($scope, $el, $attrs){
d3.selectAll($el).transition()
.duration(500)
.delay(function(){ return $scope.index*200; })
.ease('elastic')
.style('width', '100%')
.style('padding', '10px');
$scope.selectCategory = function($event, cat){
$event.stopPropagation();
targetingService.selectCategory(cat);
};
}
};
});
angular.module('myApp').directive('subCat', function(targetingService){
return {
restrict: "E",
scope: {
index: '=',
data: '='
},
template: '<li ng-transclude ng-click="selectSubCategory($event, data)"></li>',
replace: true,
transclude: true,
link: function($scope, $el, $attrs){
d3.selectAll($el).transition()
.duration(100)
.delay(function(d,i){ return 500+($scope.index*200); })
.ease('linear')
.style('height', '30px')
.style('padding', '8px');
$scope.selectSubCategory = function($event, subCat){
$event.stopPropagation();
targetingService.selectSubCategory(subCat);
};
}
};
});