Javascript 使用d3设置ng repeat指令模板动画时出现问题

Javascript 使用d3设置ng repeat指令模板动画时出现问题,javascript,angularjs,d3.js,Javascript,Angularjs,D3.js,我想用Angular和D3做一个分类列表。我已经为这个列表创建了一个指令,我的模板中的一些子节点使用ng repeat,因为我希望使用angular构建我的html而不是d3 我的问题是,当试图用d3引用ng重复元素时,它们还没有被创建。如果使用链接功能,则列表中没有项目。如果我使用compile函数,我可以看到1个列表项,但至少应该有2个 摘自小提琴: angular.module('myApp').directive('targetingCategories', function(){

我想用Angular和D3做一个分类列表。我已经为这个列表创建了一个指令,我的模板中的一些子节点使用ng repeat,因为我希望使用angular构建我的html而不是d3

我的问题是,当试图用d3引用ng重复元素时,它们还没有被创建。如果使用链接功能,则列表中没有项目。如果我使用compile函数,我可以看到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 ??
      };

    }
  };
});
angular.module('myApp')。指令('targetingCategories',function(){
返回{
限制:'E',
范围:{
数据:'='
},
模板:“”+
“
    ”+ “
  • ”+ “{{cat.name}}”+ “
      ”+ “
    • {{subcat.name}
    • ”+ “
    ”+ “
  • ”+ “
”+ '', 替换:正确, 编译:函数($tEl$attrs){ //在模板元素上附加d3,并查找列表项 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项(ul) console.log(catListFirstItem);//返回1项(第一个li) console.log(catListItems);//返回1个项目?? 返回函数($scope、$el、$attrs){ //将d3附加到实例元素并查找列表项 var vis=d3.选择($el[0]); var catList=vis.select('.catList'); var catListFirstItem=vis.select('.catlist>li'); var catListItems=vis.selectAll('.catList>li'); console.log(catList);//返回1项(ul) console.log(catListFirstItem);//返回1项(第一个li) console.log(catListItems);//返回0个项目?? }; } }; });
这个想法是让angular构建我的标记,并用d3制作动画。我喜欢d3给我的控件,而不是使用CSS动画

当我使用d3创建我的列表项时,这是一个错误。我很想再次这样做,但我认为将LIs放在模板中是一种更好的体系结构


我在想我需要调用一个编译,或者等待一个编译。我的知识几乎达到了极限,所以这里的任何教育都是值得赞赏的。

我添加了我自己的潜在答案,但没有标记,以防其他人有更好的东西

目前看来,实现这一点的一种方法是用其他嵌套指令替换主模板中的LIs,特别是“mainCategory”和“subCat”。然后,我可以将d3附加到适当的动画实例元素。通过包含索引属性属性,我可以控制延迟以使动画交错。它感觉有点复杂和“主干式”(为了对象而对象),但它解决了我的问题。它还允许我附加一些ng点击,这对于d3创建我的LIs来说是非常麻烦/不可能的

是的,我知道我的属性被称为“数据”,可能有问题,但我现在不担心这一点。如对我使用的服务/控制器/指令有任何更正,敬请谅解:)

angular.module('myApp')。指令('targetingCategories',function(){
返回{
限制:'E',
范围:{
数据:'='
},
模板:“”+
“
    ”+ ''+ “{{cat.name}}”+ “
      ”+ “{{subcat.name}}”+ “
    ”+ ''+ “
”+ '', 替换:正确 }; }); 角度。模块('myApp')。指令('mainCategory',函数(targetingService){ 返回{ 限制:“E”, 范围:{ 索引:“=”, 数据:“=” }, 模板:“
  • ”, 替换:正确, 是的, 链接:函数($scope、$el、$attrs){ d3.选择全部($el).transition() .持续时间(500) .delay(函数(){return$scope.index*200;}) .ease(“弹性”) .style(“宽度”、“100%”) .style('padding','10px'); $scope.selectCategory=函数($event,cat){ $event.stopPropagation(); targetingService。选择类别(cat); }; } }; }); 角度。模块('myApp')。指令('subCat',函数(targetingService){ 返回{ 限制:“E”, 范围:{ 索引:'=', 数据:'=' }, 模板:“
  • ”, 替换:正确, 是的, 链接:函数($scope、$el、$attrs){ d3.选择全部($el).transition() .持续时间(100) .delay(函数(d,i){返回500+($scope.index*200);}) .ease(“线性”) .style('height','30px') .style('padding','8px'); $scope.selectSubCategory=函数($event,subCat){ $event.stopPropagation(); 目标服务。选择子类别(子类别); }; } }; });
    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);
          };
        }
      };
    });