I wanted to build cool things
To unite mutual friend, and a new face
jQuery-ish
- select elements
- affect those elements via chaining API
e.g
<svg id="meetD3" width="600" height="220">
<circle r="50" cx="300" cy="110" fill="black"></circle>
</svg>
One callback API turns jQ into D3
D3's callback
d3.selectAll(".bars")
.style("background",
function(data) {
return data.risk > 0.9
? "red" : "green";
});
Data -> visual
d3.selectAll(".bars")
.style("background",
function(data) {
return data.risk > 0.9
? "red" : "green";
});
...and where does the data come from?
data()
d3.selectAll("h3")
.data([
{title: "jQuery"},
{title: "D3"}
])
Driving the document with data
<svg id="join" width="600" height="220">
<circle r="50" cx="250" cy="110"></circle>
<circle r="50" cx="450" cy="110"></circle>
</svg>
Sync DOM + data
var update = d3.selectAll('circle')
.data(data)
.attr("r", getRadius)
var enter = update.enter()
.append("circle")
var exit = update.exit()
.remove()
var circleData = [
{id: 1}, {id: 2}, {id: 3}
];
// renderCircles
.selectAll(
<el><el>
)
Add el
Remove el
.data(
{}{}{}{}
)
Add data
Remove data
=
d3 components = functions that sync <DOM> & {data}
Same input, same output
component(elements0, data1) // elements1
component(elements1, data1) // elements1
component(elements1, data2) // elements2
component(elements2, data1) // elements1
var colData = [
{id: 1}, {id: 2}, {id: 3}
];
renderCollaborator(colData);
d3 components = function over 2 data-sets
Idempotency = DOM is predictable
Idempotency = collaboration via f · g · h
Or losing benefits of Angular?
I brought 'best practice'
ng view concerns live in?
App-flavoured HTML
<!-- BOOO!! -->
<div class='profile'></div>
<!-- YAAAAY! -->
<profile></profile>
`
Approach lots of libraries have taken
<bar-chart>
<div ng-controller='ReportCtrl as ctrl'>
<bar-chart
series="ctrl.series"
y-scale="ctrl.yScale"
>
</bar-chart>
</div>
1:00 AM
Start
timeCtrl.item.time: 1:00 AM
timeForm.time.$modelValue: 1:00 AM
<form ng-controller="TimeCtrl as timeCtrl" name="timeForm">
<clock-input ng-model="timeCtrl.item.time" name="time">
</clock-input>
</form>
Our most ambitious plans were thwarted
Web-components selfishly horde <DOM>
How are newbies building cooler apps?
An unsettling realisation
Editable chart
- x/y plot
- editable data
- update on change
Ok, we've done that before
Users don't care about components
...they don't even see them
...is sacrificed to optimise the average
Users don't care about 'best practice'
'Best practice' should be making things easier
...not limiting you to easy things
Did I want to be an enterprise architect?!
No more programmer vision
Are you casting aside ng?
Writing HTML with D3?!
// the horror
var form = d3.select("#form-root")
.append("form")
.on("submit", handleSubmit)
form.append("input")
.attr("type", "range")
.attr("required", true)
form.append("input")
.attr("type", "number")
.attr("required", true)
// ... and on, and on
Beat the tools into submission!
On demand
editedSelection
.angularize(function(d, i) {
return {
controller: "ComplexFormCtrl",
locals: {
// provide Ctrl a way to hand back to D3
$edited: edited,
},
templateUrl: "editors/complexForm.html",
controllerAs: "ctrl",
injector: "app",
modules: ["app", "someFormModule"],
}
})
Let's remember why we got into code
Let's find reasons to say...