D3 + Angular
The plan
Angular directives (credit)
D3.js review (scatter-plot)
D3 in angular (<scatter-plot>)
{angular-directives}
Directives review
HTML attributes that attach behaviors
Render multiple elements
<input ng-model="search" />
<div>
<p ng-repeat="ele in myData">{{ele}}</p>
</div>
Writing directives
Directive method in JS
var myApp = angular.module("myApp", [])
// Add controller
myApp.controller('Ctrl', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
})
// Create a directive for this app
myApp.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
Writing directives
Apply directive in HTML
<div ng-app="myApp" ng-controller="Controller">
<div my-customer></div>
</div>
Better yet...
Use a templateUrl
Need to create a new .html fragment
app.directive('myCustomer', function() {
return {
templateUrl: 'my-customer.html'
};
});
<!-- myCustomer.html -->
<p>Name: {{customer.name}} Address: {{customer.address}}</p>
Better yet...
Create your directive as a new HTML element!
Include it in your HTML
app.directive('myCustomer', function() {
return {
restrict: 'E', // restrict to a new type of element
templateUrl: 'my-customer.html'
};
});
<!-- index.html -->
<body ng-app="docsRestrictDirective">
<div ng-controller="Controller">
<my-customer></my-customer>
</div>
Better yet...
Structure to pass in data
Pass data in HTML elements
app.directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
templateUrl: 'my-customer-iso.html'
};
});
<div ng-controller="Controller">
<my-customer info="naomi"></my-customer>
<hr>
<my-customer info="igor"></my-customer>
</div>
{exercise(?)}
{D3 scatter-plot}
Start in the same place
Fork my repo
Clone in desktop
Start your local server
cd "d3-demo"
python -m SimpleHTTPServer 8080
Scales
// Write a function to set your scales
var setScales = function() {
// xScale
// yScale
}
Positioning Function
/* Write a function to define the positioning of your circles
- cx attribute as the 1960 life expectancy
- cy attribute as the 2013 life expectancy
- title attribute as the country of the object
*/
Draw function
// Write a reusable drawing function for circles
var draw = function(data) {
// Set Scales
// Select all circles and bind your data to them
// Use the .enter() method to get your entering elements, and then position them using your positioning function
// Use the .exit() and .remove() methods to remove elements that are no longer in the data
// Select all circle elements within your g and transition their position using your positioning function
}
Answer time
# Checkout a new branch 'exercise-clean' from the remote branch
git checkout -b exercise-complete remotes/origin/exercise-complete
Sync repo
# Adds a new remote 'upstream', indicating repo source
git remote add upstream https://github.com/mkfreeman/d3-demo.git
# Fetch any changes from the upstream repo
git fetch upstream
# Checkout a new branch "angular-exercise" from my "angular-clean" branch
git checkout -b angular-exercise remotes/upstream/angular-clean
Our App
var myApp = angular.module("myApp", ['ui.bootstrap'])
// Bind controller and set $scope.data as your data variable
myApp.controller('myCtrl', function($scope){
$scope.data = data;
})
// Create a directive 'scatter' that creates scatterplots, and takes in $filter and $compile
myApp.directive('scatter', function($filter, $compile){
// we'll write some code in here....
})
HTML Set-up
<!-- Create a scatter directive that
takes in data and search as attributes -->
<!-- Container for your elements -->
<div class="container" id="vis">
<input placeholder="search country or region" class="form-control" ng-model="search" />
<!-- This is where your chart goes! -->
</div>
Passing in data
return {
restrict:'E', // this directive is specified as an html element <scatter>
// Define variables 'data' and 'search' as variables you've passed into HTML
scope:{
},
// Create a link function that allows dynamic element creation
link:
Manipulating HTML
// Create a link function that allows dynamic element creation
link:function(scope,elem,attrs){
// Create a variable wrapper by making a
// d3 selection the HTML element elem[0]
// Use the scope.$watch method to watch for
// changes to 'search', and executes your draw function
// Copy and paste code from your_scatter_code.js into here
}
Changes to d3 code
// Create a variable scope.filteredData using
// $filter to narrow down your data based on your search
Creating hovers
var circleFunc = function(circle) {
circle.attr('r', 10)
// Add a tooltip-append-to-body attribute, set it to true
// Add a tooltip property that has the content you want in your tooltip
}
...........
var draw = function() {
......
circles.enter().append('circle')
// Compile entering nodes so that tooltip attribute is activated
.call(function(){
$compile(this[0].parentNode)(scope);
})
}
Assignment
Personal portfolio (due next week)
angular-d3
By Michael Freeman
angular-d3
- 1,586