2016-09-11 18 views
13

Pracuję nad aplikacją kątową. Chcę dodać następującą wersję: d3 chart, jednak gdy po prostu podłączam Javascript do kontrolera, style do mojego arkusza stylów, nic się nie pojawia. Coś mi sugeruje, że Angular i D3 nie grają ładnie.Problemy z integracją D3.js (zwijane drzewo) w aplikacji Angular

Dołączyłem mój układ kątowy bez dodawania obiektu d3. Chciałbym dodać go do WorkHistory Controller/Directive/View. Jakieś sugestie na temat tego, jaki będzie właściwy sposób ustawiania tego? Dzięki!

Index.html

<!doctype html> 
    <html lang="en" ng-app="webApp"> 
    <head> 
     <meta charset="utf-8"> 

     <title>My Portfolio</title> 

     <!--Stylesheets --> 
     <link rel="stylesheet" href="styles/main.css"/> 
     <link rel="stylesheet" href="styles/d3.tree.css"/> 
     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/> 
     <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.css"/> 
     <!--Libraries --> 
     <script src="bower_components/angular/angular.min.js"></script> 
     <script src="bower_components/jquery/dist/jquery.min.js"></script> 
     <script src="bower_components/angular-route/angular-route.min.js"></script> 
     <script src="bower_components/angular-loader/angular-loader.min.js"></script> 
     <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> 
     <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
     <script src="//cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.js"></script> 
     <!--Module --> 
     <script src="scripts/modules/module.js"></script> 
     <script src="scripts/modules/d3.module.js"></script> 
     <!--Controllers --> 
     <script src="scripts/controllers/mainHeroController.js"></script> 
     <script src="scripts/controllers/workHistoryController.js"></script> 
     <!--Directives--> 
     <script src="scripts/directives/mainHero.directive.js"></script> 
     <script src="scripts/directives/mainNavbar.directive.js"></script> 
     <script src="scripts/directives/workHistory.directive.js"></script> 
    </head> 

    <!--Main Landing Page-->  
    <body> 
     <main-navbar></main-navbar> 
     <main-hero></main-hero> 
     <div id="container1" ng-controller="WorkHistoryController"> 
      <h3 id="tree-title">Work History</h3> 
       <work-history chart-data="$scope.values"></work-history> 
      </div> 
     <div id="container2"> 
      Container 2 
     </div> 
    </body> 
    </html> 

workHistory.directive.js

(function() 
    { 
    'use strict'; 

    angular 
     .module('webApp') 
     .directive('workHistory', workHistory); 

    function workHistory() 
    { 
     var directive = 
      { 
       restrict: 'E', 
       controller: 'WorkHistoryController', 
       controllerAs: 'workhistory', 
       scope: {}, 
       templateUrl: './views/workHistory.html' 
      }; 

     return directive; 

    } 
    })(); 

workHistoryController.js

(function() 
    { 

'use strict' 

angular 
    .module('webApp') 
    .controller('WorkHistoryController', WorkHistoryController); 

WorkHistoryController.$inject = ['$scope']; 

function WorkHistoryController($scope) 
    {    
    console.log($scope); 
     $scope.values = $scope.values || {};  
     $scope.values = { 
     "name": "Work History", 
     "children": [ 
      { 
      "name": "analytics", 
      "children": [ 
      { 
      "name": "cluster", 
      "children": [ 
       {"name": "AgglomerativeCluster", "size": 3938}, 
       {"name": "CommunityStructure", "size": 3812}, 
       {"name": "HierarchicalCluster", "size": 6714}, 
       {"name": "MergeEdge", "size": 743} 
      ] 
      }, 
      { 
      "name": "graph", 
      "children": [ 
       {"name": "BetweennessCentrality", "size": 3534}, 
       {"name": "LinkDistance", "size": 5731}, 
       {"name": "MaxFlowMinCut", "size": 7840}, 
       {"name": "ShortestPaths", "size": 5914}, 
       {"name": "SpanningTree", "size": 3416} 
      ] 
      }, 
      { 
      "name": "optimization", 
      "children": [ 
       {"name": "AspectRatioBanker", "size": 7074} 
      ] 
      } 
      ] 
      }, 
      { 
      "name": "animate", 
      "children": [ 
      {"name": "Easing", "size": 17010}, 
      {"name": "FunctionSequence", "size": 5842}, 
      { 
      "name": "interpolate", 
      "children": [ 
       {"name": "ArrayInterpolator", "size": 1983}, 
       {"name": "ColorInterpolator", "size": 2047}, 
       {"name": "DateInterpolator", "size": 1375}, 
       {"name": "Interpolator", "size": 8746}, 
       {"name": "MatrixInterpolator", "size": 2202}, 
       {"name": "NumberInterpolator", "size": 1382}, 
       {"name": "ObjectInterpolator", "size": 1629}, 
       {"name": "PointInterpolator", "size": 1675}, 
       {"name": "RectangleInterpolator", "size": 2042} 
      ] 
      }, 
      {"name": "ISchedulable", "size": 1041}, 
      {"name": "Parallel", "size": 5176}, 
      {"name": "Pause", "size": 449}, 
      {"name": "Scheduler", "size": 5593}, 
      {"name": "Sequence", "size": 5534}, 
      {"name": "Transition", "size": 9201}, 
      {"name": "Transitioner", "size": 19975}, 
      {"name": "TransitionEvent", "size": 1116}, 
      {"name": "Tween", "size": 6006} 
      ] 
      }, 
      { 
      "name": "data", 
      "children": [ 
      { 
      "name": "converters", 
      "children": [ 
       {"name": "Converters", "size": 721}, 
       {"name": "DelimitedTextConverter", "size": 4294}, 
       {"name": "GraphMLConverter", "size": 9800}, 
       {"name": "IDataConverter", "size": 1314}, 
       {"name": "JSONConverter", "size": 2220} 
      ] 
      }, 
      {"name": "DataField", "size": 1759}, 
      {"name": "DataSchema", "size": 2165}, 
      {"name": "DataSet", "size": 586}, 
      {"name": "DataSource", "size": 3331}, 
      {"name": "DataTable", "size": 772}, 
      {"name": "DataUtil", "size": 3322} 
      ] 
      }, 
      { 
      "name": "display", 
      "children": [ 
      {"name": "DirtySprite", "size": 8833}, 
      {"name": "LineSprite", "size": 1732}, 
      {"name": "RectSprite", "size": 3623}, 
      {"name": "TextSprite", "size": 10066} 
      ] 
      }, 
      { 
      "name": "flex", 
      "children": [ 
      {"name": "FlareVis", "size": 4116} 
      ] 
      }, 
      { 
      "name": "physics", 
      "children": [ 
      {"name": "DragForce", "size": 1082}, 
      {"name": "GravityForce", "size": 1336}, 
      {"name": "IForce", "size": 319}, 
      {"name": "NBodyForce", "size": 10498}, 
      {"name": "Particle", "size": 2822}, 
      {"name": "Simulation", "size": 9983}, 
      {"name": "Spring", "size": 2213}, 
      {"name": "SpringForce", "size": 1681} 
      ] 
      }, 
      { 
      "name": "query", 
      "children": [ 
      {"name": "AggregateExpression", "size": 1616}, 
      {"name": "And", "size": 1027}, 
      {"name": "Arithmetic", "size": 3891}, 
      {"name": "Average", "size": 891}, 
      {"name": "BinaryExpression", "size": 2893}, 
      {"name": "Comparison", "size": 5103}, 
      {"name": "CompositeExpression", "size": 3677}, 
      {"name": "Count", "size": 781}, 
      {"name": "DateUtil", "size": 4141}, 
      {"name": "Distinct", "size": 933}, 
      {"name": "Expression", "size": 5130}, 
      {"name": "ExpressionIterator", "size": 3617}, 
      {"name": "Fn", "size": 3240}, 
      {"name": "If", "size": 2732}, 
      {"name": "IsA", "size": 2039}, 
      {"name": "Literal", "size": 1214}, 
      {"name": "Match", "size": 3748}, 
      {"name": "Maximum", "size": 843}, 
      { 
      "name": "methods", 
      "children": [ 
       {"name": "add", "size": 593}, 
       {"name": "and", "size": 330}, 
       {"name": "average", "size": 287}, 
       {"name": "count", "size": 277}, 
       {"name": "distinct", "size": 292}, 
       {"name": "div", "size": 595}, 
       {"name": "eq", "size": 594}, 
       {"name": "fn", "size": 460}, 
       {"name": "gt", "size": 603}, 
       {"name": "gte", "size": 625}, 
       {"name": "iff", "size": 748}, 
       {"name": "isa", "size": 461}, 
       {"name": "lt", "size": 597}, 
       {"name": "lte", "size": 619}, 
       {"name": "max", "size": 283}, 
       {"name": "min", "size": 283}, 
       {"name": "mod", "size": 591}, 
       {"name": "mul", "size": 603}, 
       {"name": "neq", "size": 599}, 
       {"name": "not", "size": 386}, 
       {"name": "or", "size": 323}, 
       {"name": "orderby", "size": 307}, 
       {"name": "range", "size": 772}, 
       {"name": "select", "size": 296}, 
       {"name": "stddev", "size": 363}, 
       {"name": "sub", "size": 600}, 
       {"name": "sum", "size": 280}, 
       {"name": "update", "size": 307}, 
       {"name": "variance", "size": 335}, 
       {"name": "where", "size": 299}, 
       {"name": "xor", "size": 354}, 
       {"name": "_", "size": 264} 
      ] 
      }, 
      {"name": "Minimum", "size": 843}, 
      {"name": "Not", "size": 1554}, 
      {"name": "Or", "size": 970}, 
      {"name": "Query", "size": 13896}, 
      {"name": "Range", "size": 1594}, 
      {"name": "StringUtil", "size": 4130}, 
      {"name": "Sum", "size": 791}, 
      {"name": "Variable", "size": 1124}, 
      {"name": "Variance", "size": 1876}, 
      {"name": "Xor", "size": 1101} 
      ] 
      }, 
      { 
      "name": "scale", 
      "children": [ 
      {"name": "IScaleMap", "size": 2105}, 
      {"name": "LinearScale", "size": 1316}, 
      {"name": "LogScale", "size": 3151}, 
      {"name": "OrdinalScale", "size": 3770}, 
      {"name": "QuantileScale", "size": 2435}, 
      {"name": "QuantitativeScale", "size": 4839}, 
      {"name": "RootScale", "size": 1756}, 
      {"name": "Scale", "size": 4268}, 
      {"name": "ScaleType", "size": 1821}, 
      {"name": "TimeScale", "size": 5833} 
      ] 
      }, 
      { 
      "name": "util", 
      "children": [ 
      {"name": "Arrays", "size": 8258}, 
      {"name": "Colors", "size": 10001}, 
      {"name": "Dates", "size": 8217}, 
      {"name": "Displays", "size": 12555}, 
      {"name": "Filter", "size": 2324}, 
      {"name": "Geometry", "size": 10993}, 
      { 
      "name": "heap", 
      "children": [ 
       {"name": "FibonacciHeap", "size": 9354}, 
       {"name": "HeapNode", "size": 1233} 
      ] 
      }, 
      {"name": "IEvaluable", "size": 335}, 
      {"name": "IPredicate", "size": 383}, 
      {"name": "IValueProxy", "size": 874}, 
      { 
      "name": "math", 
      "children": [ 
       {"name": "DenseMatrix", "size": 3165}, 
       {"name": "IMatrix", "size": 2815}, 
       {"name": "SparseMatrix", "size": 3366} 
      ] 
      }, 
      {"name": "Maths", "size": 17705}, 
      {"name": "Orientation", "size": 1486}, 
      { 
      "name": "palette", 
      "children": [ 
       {"name": "ColorPalette", "size": 6367}, 
       {"name": "Palette", "size": 1229}, 
       {"name": "ShapePalette", "size": 2059}, 
       {"name": "SizePalette", "size": 2291} 
      ] 
      }, 
      {"name": "Property", "size": 5559}, 
      {"name": "Shapes", "size": 19118}, 
      {"name": "Sort", "size": 6887}, 
      {"name": "Stats", "size": 6557}, 
      {"name": "Strings", "size": 22026} 
      ] 
      }, 
      { 
      "name": "vis", 
      "children": [ 
      { 
      "name": "axis", 
      "children": [ 
       {"name": "Axes", "size": 1302}, 
       {"name": "Axis", "size": 24593}, 
       {"name": "AxisGridLine", "size": 652}, 
       {"name": "AxisLabel", "size": 636}, 
       {"name": "CartesianAxes", "size": 6703} 
      ] 
      }, 
      { 
      "name": "controls", 
      "children": [ 
       {"name": "AnchorControl", "size": 2138}, 
       {"name": "ClickControl", "size": 3824}, 
       {"name": "Control", "size": 1353}, 
       {"name": "ControlList", "size": 4665}, 
       {"name": "DragControl", "size": 2649}, 
       {"name": "ExpandControl", "size": 2832}, 
       {"name": "HoverControl", "size": 4896}, 
       {"name": "IControl", "size": 763}, 
       {"name": "PanZoomControl", "size": 5222}, 
       {"name": "SelectionControl", "size": 7862}, 
       {"name": "TooltipControl", "size": 8435} 
      ] 
      }, 
      { 
      "name": "data", 
      "children": [ 
       {"name": "Data", "size": 20544}, 
       {"name": "DataList", "size": 19788}, 
       {"name": "DataSprite", "size": 10349}, 
       {"name": "EdgeSprite", "size": 3301}, 
       {"name": "NodeSprite", "size": 19382}, 
       { 
       "name": "render", 
       "children": [ 
       {"name": "ArrowType", "size": 698}, 
       {"name": "EdgeRenderer", "size": 5569}, 
       {"name": "IRenderer", "size": 353}, 
       {"name": "ShapeRenderer", "size": 2247} 
       ] 
       }, 
       {"name": "ScaleBinding", "size": 11275}, 
       {"name": "Tree", "size": 7147}, 
       {"name": "TreeBuilder", "size": 9930} 
      ] 
      }, 
      { 
      "name": "events", 
      "children": [ 
       {"name": "DataEvent", "size": 2313}, 
       {"name": "SelectionEvent", "size": 1880}, 
       {"name": "TooltipEvent", "size": 1701}, 
       {"name": "VisualizationEvent", "size": 1117} 
      ] 
      }, 
      { 
      "name": "legend", 
      "children": [ 
       {"name": "Legend", "size": 20859}, 
       {"name": "LegendItem", "size": 4614}, 
       {"name": "LegendRange", "size": 10530} 
      ] 
      }, 
      { 
      "name": "operator", 
      "children": [ 
       { 
       "name": "distortion", 
       "children": [ 
       {"name": "BifocalDistortion", "size": 4461}, 
       {"name": "Distortion", "size": 6314}, 
       {"name": "FisheyeDistortion", "size": 3444} 
       ] 
       }, 
       { 
       "name": "encoder", 
       "children": [ 
       {"name": "ColorEncoder", "size": 3179}, 
       {"name": "Encoder", "size": 4060}, 
       {"name": "PropertyEncoder", "size": 4138}, 
       {"name": "ShapeEncoder", "size": 1690}, 
       {"name": "SizeEncoder", "size": 1830} 
       ] 
       }, 
       { 
       "name": "filter", 
       "children": [ 
       {"name": "FisheyeTreeFilter", "size": 5219}, 
       {"name": "GraphDistanceFilter", "size": 3165}, 
       {"name": "VisibilityFilter", "size": 3509} 
       ] 
       }, 
       {"name": "IOperator", "size": 1286}, 
       { 
       "name": "label", 
       "children": [ 
       {"name": "Labeler", "size": 9956}, 
       {"name": "RadialLabeler", "size": 3899}, 
       {"name": "StackedAreaLabeler", "size": 3202} 
       ] 
       }, 
       { 
       "name": "layout", 
       "children": [ 
       {"name": "AxisLayout", "size": 6725}, 
       {"name": "BundledEdgeRouter", "size": 3727}, 
       {"name": "CircleLayout", "size": 9317}, 
       {"name": "CirclePackingLayout", "size": 12003}, 
       {"name": "DendrogramLayout", "size": 4853}, 
       {"name": "ForceDirectedLayout", "size": 8411}, 
       {"name": "IcicleTreeLayout", "size": 4864}, 
       {"name": "IndentedTreeLayout", "size": 3174}, 
       {"name": "Layout", "size": 7881}, 
       {"name": "NodeLinkTreeLayout", "size": 12870}, 
       {"name": "PieLayout", "size": 2728}, 
       {"name": "RadialTreeLayout", "size": 12348}, 
       {"name": "RandomLayout", "size": 870}, 
       {"name": "StackedAreaLayout", "size": 9121}, 
       {"name": "TreeMapLayout", "size": 9191} 
       ] 
       }, 
       {"name": "Operator", "size": 2490}, 
       {"name": "OperatorList", "size": 5248}, 
       {"name": "OperatorSequence", "size": 4190}, 
       {"name": "OperatorSwitch", "size": 2581}, 
       {"name": "SortOperator", "size": 2023} 
      ] 
      }, 
      {"name": "Visualization", "size": 16540} 
      ] 
      } 
     ] 
     }; 
    } 
})(); 

workHistory.html

//insert d3 view here 

main.css

//insert d3 styles here 

Odpowiedz

4

Jest bardzo prosty do złożenia wniosku angular i korzystania d3 w aplikacji. Przede wszystkim musisz dowiedzieć się czegoś o strukturze angular. Jak wiesz, do korzystania z biblioteki kątowej potrzebujesz ng-app. Możesz ją zdefiniować w tagu html lub body. Jeśli chcesz udostępniać dane między dyrektywami lub pracować z kątowym services potrzebujesz kontrolera kątowego. W tym przypadku $scope jest dzielony między kontrolerem i dyrektywami. Ostatnią funkcją, której musisz użyć, jest dyrektywa. Tak więc zgodnie z tym fragmentem znormalizujmy Twój kod. Przede wszystkim nie należy definiować dyrektywy dla parametru css, wystarczy dodać wszystkie do pliku i wprowadzić go na stronę główną lub wstawić do znacznika <style>. Jak już wspomniałem, dyrektywa używa tylko funkcji JavaScript. Więc Wdrożenie kątową aplikację:

var app = angular.module('App'); 
var ctrl = app.controller("treeCrtl", ["$scope", function ($scope) { 
}]); 

Są to dwie funkcje, ng-app i kątowa kontroler i jest to dyrektywa.

ctrl.directive("workHistory", function() { 
     return { 
       restrict: 'E', 
       link: function link(scope, el, attr) { 

        var div = d3.select("body") 
         .append("div") // declare the tooltip div 
         .attr("class", "tooltip") 
         .style("opacity", 0); 

        var margin = { top: 20, right: 120, bottom: 20, left: 120 }, 
         width = 960 - margin.right - margin.left, 
         height = 800 - margin.top - margin.bottom; 
        var i = 0,duration = 750,root,select2_data; 
        var diameter = 960; 
        var tree = d3.layout.tree() 
         .size([height, width]); 

        var diagonal = d3.svg.diagonal() 
         .projection(function (d) { return [d.y, d.x]; }); 

        var svg = d3.select(el[0]).append("svg") 
         .attr("width", width + margin.right + margin.left) 
         .attr("height", height + margin.top + margin.bottom) 
         .append("g") 
         .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

        //recursively collapse children 
        function collapse(d) { 
         if (d.children) { 
          d._children = d.children; 
          d._children.forEach(collapse); 
          d.children = null; 
         } 
        } 

        // Toggle children on click. 
        function click(d) { 
         if (d.children) { 
          d._children = d.children; 
          d.children = null; 
         } 
         else { 
          d.children = d._children; 
          d._children = null; 
         } 
         update(d); 
        } 

        function openPaths(paths) { 
         for (var i = 0; i < paths.length; i++) { 
          if (paths[i].id !== "1") {//i.e. not root 
           paths[i].class = 'found'; 
           if (paths[i]._children) { //if children are hidden: open them, otherwise: don't do anything 
            paths[i].children = paths[i]._children; 
            paths[i]._children = null; 
           } 
           update(paths[i]); 
          } 
         } 
        } 


         root = values; 
         select2_data = extract_select2_data(values, [], 0)[1];//I know, not the prettiest... 
         root.x0 = height/2; 
         root.y0 = 0; 
         root.children.forEach(collapse); 
         update(root); 
         //init search box 
         $("#search").select2({ 
          data: select2_data, 
          containerCssClass: "search" 
         }); 


        //attach search box listener 
        $("#search").on("select2-selecting", function(e) { 
         var paths = searchTree(root, e.object.text, []); 
         if (typeof (paths) !== "undefined") { 
          openPaths(paths); 
         } else { 
          alert(e.object.text + " not found!"); 
         } 
        }); 

        d3.select(self.frameElement).style("height", "800px"); 

        function update(source) { 
         // Compute the new tree layout. 
         var nodes = tree.nodes(root).reverse(), 
         links = tree.links(nodes); 

         // Normalize for fixed-depth. 
         nodes.forEach(function (d) { d.y = d.depth * 180; }); 

         // Update the nodes… 
         var node = svg.selectAll("g.node") 
          .data(nodes, function (d) { return d.id || (d.id = ++i); }); 

         // Enter any new nodes at the parent's previous position. 
         var nodeEnter = node.enter().append("g") 
          .attr("class", "node") 
         .attr("transform", function (d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) 
         .on("click", click); 

         nodeEnter.append("circle") 
         .attr("r", 1e-6) 
         .style("fill", function (d) { return d._children ? "lightsteelblue" : "#fff"; }); 

         nodeEnter.append("text") 
          .attr("x", function (d) { return d.children || d._children ? -10 : 10; }) 
          .attr("dy", ".35em") 
          .attr("text-anchor", function (d) { return d.children || d._children ? "end" : "start"; }) 
          .text(function (d) { return d.name; }) 
          .style("fill-opacity", 1e-6); 

         // Transition nodes to their new position. 
         var nodeUpdate = node.transition() 
          .duration(duration) 
          .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; }); 

         nodeUpdate.select("circle") 
          .attr("r", 4.5) 
          .style("fill", function (d) { 
           if (d.class === "found") { 
            return "#ff4136"; //red 
           } 
           else if (d._children) { 
            return "lightsteelblue"; 
           } 
           else { 
            return "#fff"; 
           } 
          }) 
          .style("stroke", function (d) { 
           if (d.class === "found") { 
            return "#ff4136"; //red 
           } 
          }); 

         nodeUpdate.select("text") 
          .style("fill-opacity", 1); 

         // Transition exiting nodes to the parent's new position. 
         var nodeExit = node.exit().transition() 
          .duration(duration) 
          .attr("transform", function (d) { return "translate(" + source.y + "," + source.x + ")"; }) 
          .remove(); 

         nodeExit.select("circle") 
          .attr("r", 1e-6); 

         nodeExit.select("text") 
          .style("fill-opacity", 1e-6); 

         // Update the links… 
         var link = svg.selectAll("path.link") 
          .data(links, function (d) { return d.target.id; }); 

         // Enter any new links at the parent's previous position. 
         link.enter().insert("path", "g") 
          .attr("class", "link") 
          .attr("d", function (d) { 
           var o = { x: source.x0, y: source.y0 }; 
           return diagonal({ source: o, target: o }); 
          }); 

         // Transition links to their new position. 
         link.transition() 
          .duration(duration) 
          .attr("d", diagonal) 
          .style("stroke", function (d) { 
           if (d.target.class === "found") { 
            return "#ff4136"; 
           } 
          }); 

         // Transition exiting nodes to the parent's new position. 
         link.exit().transition() 
          .duration(duration) 
          .attr("d", function (d) { 
           var o = { x: source.x, y: source.y }; 
           return diagonal({ source: o, target: o }); 
          }) 
          .remove(); 

         // Stash the old positions for transition. 
         nodes.forEach(function (d) { 
          d.x0 = d.x; 
          d.y0 = d.y; 
         }); 
        } 

        function searchTree(obj, search, path) { 
         if (obj.name === search) { //if search is found return, add the object to the path and return it 
          path.push(obj); 
          return path; 
         } 
         else if (obj.children || obj._children) { //if children are collapsed d3 object will have them instantiated as _children 
          var children = (obj.children) ? obj.children : obj._children; 
          for (var i = 0; i < children.length; i++) { 
           path.push(obj);// we assume this path is the right one 
           var found = searchTree(children[i], search, path); 
           if (found) {// we were right, this should return the bubbled-up path from the first if statement 
            return found; 
           } 
           else {//we were wrong, remove this parent from the path and continue iterating 
            path.pop(); 
           } 
          } 
         } 
         else {//not the right object, return false so it will continue to iterate in the loop 
          return false; 
         } 
        } 

        function extract_select2_data(node, leaves, index) { 
         if (node.children) { 
          for (var i = 0; i < node.children.length; i++) { 
           index = extract_select2_data(node.children[i], leaves, index)[0]; 
          } 
         } 
         else { 
          leaves.push({ id: ++index, text: node.name }); 
         } 
         return [index, leaves]; 
        } 

       } 
      } 
     }); 

Istnieje kilka punktów muszę wspomnieć:

1- Jeśli masz do wdrożenia różnych dyrektyw, wystarczy użyć tego samego formatu z różnymi nazwami.

2- Aby połączyć swój kod ze znacznikiem dyrektywy, należy użyć tego rodzaju kodowania: d3.select(el[0]), Uwaga el to parametr funkcji łącza.

3- Jeśli używasz innego katalogu dla flare.json zastąpić tę część:

root = values; 
select2_data = extract_select2_data(values, [], 0)[1];//I know, not the prettiest... 
root.x0 = height/2; 
root.y0 = 0; 
root.children.forEach(collapse); 
update(root); 
//init search box 
$("#search").select2({ 
    data: select2_data, 
    containerCssClass: "search" 
}); 

z tym:

d3.json("flare.json", function(error,values){ 
     root = values; 
     select2_data = extract_select2_data(values,[],0)[1];//I know, not the prettiest... 
     root.x0 = height/2; 
     root.y0 = 0; 
     root.children.forEach(collapse); 
     update(root); 
     //init search box 
     $("#search").select2({ 
      data: select2_data, 
      containerCssClass: "search" 
     }); 
    }); 

Oto cały kod:

Js część:

 var app = angular.module('App'); 
     var ctrl = app.controller("treeCrtl", ["$scope", function ($scope) { 

     }]); 
     ctrl.directive("workHistory", function() { 
     return { 
       restrict: 'E', 
       link: function link(scope, el, attr) { 

        var div = d3.select("body") 
         .append("div") // declare the tooltip div 
         .attr("class", "tooltip") 
         .style("opacity", 0); 

        var margin = { top: 20, right: 120, bottom: 20, left: 120 }, 
         width = 960 - margin.right - margin.left, 
         height = 800 - margin.top - margin.bottom; 
        var i = 0,duration = 750,root,select2_data; 
        var diameter = 960; 
        var tree = d3.layout.tree() 
         .size([height, width]); 

        var diagonal = d3.svg.diagonal() 
         .projection(function (d) { return [d.y, d.x]; }); 

        var svg = d3.select(el[0]).append("svg") 
         .attr("width", width + margin.right + margin.left) 
         .attr("height", height + margin.top + margin.bottom) 
         .append("g") 
         .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

        //recursively collapse children 
        function collapse(d) { 
         if (d.children) { 
          d._children = d.children; 
          d._children.forEach(collapse); 
          d.children = null; 
         } 
        } 

        // Toggle children on click. 
        function click(d) { 
         if (d.children) { 
          d._children = d.children; 
          d.children = null; 
         } 
         else { 
          d.children = d._children; 
          d._children = null; 
         } 
         update(d); 
        } 

        function openPaths(paths) { 
         for (var i = 0; i < paths.length; i++) { 
          if (paths[i].id !== "1") {//i.e. not root 
           paths[i].class = 'found'; 
           if (paths[i]._children) { //if children are hidden: open them, otherwise: don't do anything 
            paths[i].children = paths[i]._children; 
            paths[i]._children = null; 
           } 
           update(paths[i]); 
          } 
         } 
        } 

        root = values; 
        //values is the flare.json 
        select2_data = extract_select2_data(values, [], 0)[1];//I know, not the prettiest... 
        root.x0 = height/2; 
        root.y0 = 0; 
        root.children.forEach(collapse); 
        update(root); 
        //init search box 
        $("#search").select2({ 
        data: select2_data, 
        containerCssClass: "search" 
        }); 

        //attach search box listener 
        $("#search").on("select2-selecting", function(e) { 
         var paths = searchTree(root, e.object.text, []); 
         if (typeof (paths) !== "undefined") { 
          openPaths(paths); 
         } else { 
          alert(e.object.text + " not found!"); 
         } 
        }); 

        d3.select(self.frameElement).style("height", "800px"); 

        function update(source) { 
         // Compute the new tree layout. 
         var nodes = tree.nodes(root).reverse(), 
         links = tree.links(nodes); 

         // Normalize for fixed-depth. 
         nodes.forEach(function (d) { d.y = d.depth * 180; }); 

         // Update the nodes… 
         var node = svg.selectAll("g.node") 
          .data(nodes, function (d) { return d.id || (d.id = ++i); }); 

         // Enter any new nodes at the parent's previous position. 
         var nodeEnter = node.enter().append("g") 
          .attr("class", "node") 
         .attr("transform", function (d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) 
         .on("click", click); 

         nodeEnter.append("circle") 
         .attr("r", 1e-6) 
         .style("fill", function (d) { return d._children ? "lightsteelblue" : "#fff"; }); 

         nodeEnter.append("text") 
          .attr("x", function (d) { return d.children || d._children ? -10 : 10; }) 
          .attr("dy", ".35em") 
          .attr("text-anchor", function (d) { return d.children || d._children ? "end" : "start"; }) 
          .text(function (d) { return d.name; }) 
          .style("fill-opacity", 1e-6); 

         // Transition nodes to their new position. 
         var nodeUpdate = node.transition() 
          .duration(duration) 
          .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; }); 

         nodeUpdate.select("circle") 
          .attr("r", 4.5) 
          .style("fill", function (d) { 
           if (d.class === "found") { 
            return "#ff4136"; //red 
           } 
           else if (d._children) { 
            return "lightsteelblue"; 
           } 
           else { 
            return "#fff"; 
           } 
          }) 
          .style("stroke", function (d) { 
           if (d.class === "found") { 
            return "#ff4136"; //red 
           } 
          }); 

         nodeUpdate.select("text") 
          .style("fill-opacity", 1); 

         // Transition exiting nodes to the parent's new position. 
         var nodeExit = node.exit().transition() 
          .duration(duration) 
          .attr("transform", function (d) { return "translate(" + source.y + "," + source.x + ")"; }) 
          .remove(); 

         nodeExit.select("circle") 
          .attr("r", 1e-6); 

         nodeExit.select("text") 
          .style("fill-opacity", 1e-6); 

         // Update the links… 
         var link = svg.selectAll("path.link") 
          .data(links, function (d) { return d.target.id; }); 

         // Enter any new links at the parent's previous position. 
         link.enter().insert("path", "g") 
          .attr("class", "link") 
          .attr("d", function (d) { 
           var o = { x: source.x0, y: source.y0 }; 
           return diagonal({ source: o, target: o }); 
          }); 

         // Transition links to their new position. 
         link.transition() 
          .duration(duration) 
          .attr("d", diagonal) 
          .style("stroke", function (d) { 
           if (d.target.class === "found") { 
            return "#ff4136"; 
           } 
          }); 

         // Transition exiting nodes to the parent's new position. 
         link.exit().transition() 
          .duration(duration) 
          .attr("d", function (d) { 
           var o = { x: source.x, y: source.y }; 
           return diagonal({ source: o, target: o }); 
          }) 
          .remove(); 

         // Stash the old positions for transition. 
         nodes.forEach(function (d) { 
          d.x0 = d.x; 
          d.y0 = d.y; 
         }); 
        } 

        function searchTree(obj, search, path) { 
         if (obj.name === search) { //if search is found return, add the object to the path and return it 
          path.push(obj); 
          return path; 
         } 
         else if (obj.children || obj._children) { //if children are collapsed d3 object will have them instantiated as _children 
          var children = (obj.children) ? obj.children : obj._children; 
          for (var i = 0; i < children.length; i++) { 
           path.push(obj);// we assume this path is the right one 
           var found = searchTree(children[i], search, path); 
           if (found) {// we were right, this should return the bubbled-up path from the first if statement 
            return found; 
           } 
           else {//we were wrong, remove this parent from the path and continue iterating 
            path.pop(); 
           } 
          } 
         } 
         else {//not the right object, return false so it will continue to iterate in the loop 
          return false; 
         } 
        } 

        function extract_select2_data(node, leaves, index) { 
         if (node.children) { 
          for (var i = 0; i < node.children.length; i++) { 
           index = extract_select2_data(node.children[i], leaves, index)[0]; 
          } 
         } 
         else { 
          leaves.push({ id: ++index, text: node.name }); 
         } 
         return [index, leaves]; 
        } 

       } 
      } 
     }); 

Html część:

<html> 
<head> 
    <title>flare</title> 
    <meta charset="utf-8" /> 
    <style> 
     .node { 
      cursor: pointer; 
     } 

     .node circle { 
      fill: #fff; 
      stroke: steelblue; 
      stroke-width: 1.5px; 
     } 

     .found { 
      fill: #ff4136; 
      stroke: #ff4136; 
     } 
     .node text { 
      font: 10px sans-serif; 
     } 

     .link { 
      fill: none; 
      stroke: #ccc; 
      stroke-width: 1.5px; 
     } 
     /*Just to ensure the select2 box is "glued" to the top*/ 
     .search { 
      width: 100%; 
     } 
    </style> 
    <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.css"> 
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script> 
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.js"></script> 
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
</head> 
<body ng-app="App" ng-controller="treeCrtl"> 
    <div id="search"></div> 
    <work-history></work-history> 
</body> 
</html> 

Aktualizacja 1

Zrobiłem żywo working demo, mam nadzieję, że to pomoże.

+0

Jeśli nadal nie wiesz, jak zintegrować aplikację kątową, sprawdź aktualizację 1. – Gabriel

+0

Hej, Gabriel, działa, dziękuję! Dla czystszego kodu, jak mogę migrować dane z dyrektywy do kontrolera, w przykładzie przed aktualizacją 'treeCtrl' jest pustym kontrolerem. –

+2

Bardzo łatwo jest przenieść dane z dyrektywy do kontrolera, wystarczy dodać dane do '$ scope' w kontrolerze i odczytać dane z dyrektywy w" zasięgu ". Na przykład 'scope.data = root;' umieść dane root'a w 'scope.data' i uzyskaj dostęp do danych w kontrolerze tylko z tą strukturą:' $ scope.data'. Kontroler w Angular wygląda jak kontroler w modelu 'asp.net mvc'. Jeśli masz dyrektywę Multi, po prostu zdefiniuj kontroler i użyj dyrektyw z udostępnionymi danymi i funkcjami z niego. – Gabriel

2

więc trudno wiedzieć na pewno, nie widząc swój rzeczywisty kod D3, ale wierzę, że problem jest gdzie jesteś ładowania twój skrypt D3.

Zasadniczo uruchamiasz skrypt D3 w kontrolerze, co jest za późno. Do czasu utworzenia kontrolera DOM został już renderowany przez Angular. Dotyczy to nawet dyrektywy. Aby manipulować DOMem (np. Dołączając wizualizację D3), musisz przenieść skrypt D3 do funkcji dyrektywy link. Funkcja link w dyrektywie jest uruchamiana raz dla każdej instancji dyrektywy w celu skompilowania widoku dyrektywy z odpowiednim zakresem i utworzenia DOM.

function link (scope, element, attributes) { 
    // D3 code here 
} 

var directive = 
    { 
    restrict: 'E', 
    link: link, 
    controller: 'WorkHistoryController', 
    controllerAs: 'workhistory', 
    scope: {}, 
    templateUrl: './views/workHistory.html' 
    }; 

return directive; 

Here's a good example of creating a D3 directive

And here's a good overview of Angular directives which details the link phase