Kode_12 Kode_12 - 2 months ago 20
AngularJS Question

Having trouble integrating D3.js (collapsible tree) into Angular application

I'm working on an angular application. I want to add in the following d3 chart, however when I simply plug in the Javascript into my controller, styles into my stylesheet, nothing appears. Something is suggesting to me that the Angular and D3 aren't playing nice.

I have attached my angular setup without adding in the d3 object. I would like to add it into the workHistory Controller/Directive/View. Any suggestions on what the proper way to set this up would be? Thanks!

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="bower_components/bootstrap/dist/css/bootstrap.min.css"/>
<!--Libraries -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/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="http://d3js.org/d3.v3.min.js"></script>
<!--Module -->
<script src="scripts/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 ng-app="webApp">
<main-navbar></main-navbar>
<main-hero></main-hero>
<div id="container1">
<work-history></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 = [];

function WorkHistoryController()
{
insert D3 script here
}

})()


workHistory.html

//insert d3 view here


main.css

//insert d3 styles here

Answer

So it's hard to know for sure without seeing your actual D3 code, but I believe the issue is where you're loading your D3 script.

Basically, you're running your D3 script in your controller, which is too late. By the time a controller is instantiated, the DOM has already been rendered by Angular. This is true even on a directive. To manipulate the DOM (like appending a D3 visualization), you need to move your D3 script to the directive's link function. The link function in a directive is run once for each instance of the directive in order to compile the directive's view against the correct scope and create the 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

Comments