Skip to content

Commit 9ba150d

Browse files
committed
feat(instance): give access to the c3js API using the instance attribute on the directive
1 parent 45f640e commit 9ba150d

File tree

11 files changed

+135
-37
lines changed

11 files changed

+135
-37
lines changed

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,22 @@ angular
5555
}
5656
};
5757

58+
// optional (direct access to c3js API http://c3js.org/reference.html#api)
59+
$scope.instance = null;
60+
5861
});
5962
```
6063

6164
Then you are ready to use the directive in your view:
6265
```html
6366
<div ng-controller="Controller">
64-
<angular-chart options="options"></angular-chart>
67+
<angular-chart options="options" instance="instance"></angular-chart>
6568
</div>
6669
```
6770

6871
[learn how to upgrade from v0.2.x](#upgrade-02x-to-030)
6972

70-
## API
73+
## OPTIONS
7174

7275
The options object can contain four different keys:
7376
* `data` JSON based data you want to visualize
@@ -178,6 +181,16 @@ Pie-, Donut chart: _(Currently adding a selection in the Array will not add the
178181
}
179182
```
180183

184+
185+
## INSTANCE
186+
187+
The `instance` attribute of the directive will be filled with a promise on initialization.
188+
The promise will be fulfilled the first time the chart is generated.
189+
Every time a new chart instance is created the `instance` of the directive will be updated as well.
190+
191+
You can call all [c3js API calls](http://c3js.org/reference.html#api) such as `flow()`, `resize()`, ... on the chart instance.
192+
193+
181194
## custom Style
182195
The whole chart is based on SVG, which allows you to stlye most parts using CSS.
183196
The documentation of c3.js provides a few [examples](http://c3js.org/examples.html#style) on how to style your chart.

angular-chart.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
return {
1717
restrict: 'EA',
1818
scope: {
19-
options: '='
19+
options: '=',
20+
instance: '=?'
2021
},
2122
controller: 'AngularChartController'
2223
};
@@ -467,15 +468,16 @@
467468
'use strict';
468469

469470
/* istanbul ignore next */
470-
AngularChartService.$inject = ['$timeout', 'AngularChartWatcher', 'AngularChartConverter', 'AngularChartState'];
471+
AngularChartService.$inject = ['$timeout', '$q', 'AngularChartWatcher', 'AngularChartConverter', 'AngularChartState'];
471472
var angular = window.angular ? window.angular : 'undefined' !== typeof require ? require('angular') : undefined;
472473
/* istanbul ignore next */
473474
var c3 = window.c3 ? window.c3 : 'undefined' !== typeof require ? require('c3') : undefined;
474475

475-
function AngularChartService($timeout, AngularChartWatcher, AngularChartConverter, AngularChartState) {
476+
function AngularChartService($timeout, $q, AngularChartWatcher, AngularChartConverter, AngularChartState) {
476477

477478
var ChartService = function(baseConfig, scope) {
478-
this.chart = null;
479+
this.deferredChart = $q.defer();
480+
this.chart = this.deferredChart.promise;
479481
this.baseConfiguration = {};
480482
this.configuration = {};
481483
this.scopeReference = null;
@@ -535,8 +537,13 @@
535537
this.convertOptions();
536538
this.applyChartOptions();
537539
this.synchronizeState();
538-
this.generateChart();
539-
this.stateCallback();
540+
541+
// call long running generation async
542+
var chartService = this;
543+
$timeout(function() {
544+
chartService.generateChart(chartService);
545+
chartService.stateCallback();
546+
});
540547
};
541548

542549
/**
@@ -588,11 +595,15 @@
588595
/**
589596
* Render the chart.
590597
*/
591-
ChartService.prototype.generateChart = function() {
598+
ChartService.prototype.generateChart = function(chartService) {
592599
// TODO add own onresize listener?
593600
// TODO regenerate chart only one or two times per second
594601
// TODO evaluate if it makes sense to destroy the chart first
595-
this.chart = c3.generate(this.configuration);
602+
603+
var chart = c3.generate(chartService.configuration);
604+
chartService.deferredChart.resolve(chart);
605+
chartService.scopeReference.instance = chart;
606+
chartService.chart = chart;
596607
};
597608

598609
/**
@@ -607,7 +618,9 @@
607618
* Destroy the chart if one ist present.
608619
*/
609620
ChartService.prototype.destroyChart = function() {
610-
this.chart.destroy();
621+
if (this.chart.destroy) {
622+
this.chart.destroy();
623+
}
611624
};
612625

613626
ChartService.prototype.merge = angular.merge || deepMerge;
@@ -851,7 +864,7 @@
851864
unwrapPromise();
852865
addIdentifier();
853866
addInlineStyle();
854-
chartService = AngularChartService.getInstance(configuration, $scope);
867+
getInstance();
855868
registerDestroyListener();
856869
}
857870

@@ -880,6 +893,11 @@
880893
angular.element($element).css('display', 'block');
881894
}
882895

896+
function getInstance() {
897+
chartService = AngularChartService.getInstance(configuration, $scope);
898+
$scope.instance = chartService.chart;
899+
}
900+
883901
/**
884902
* Remove all references when directive is destroyed
885903
*/

angular-chart.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

debug/debug-controller.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@
131131
console.log('new options', vm.timestampOptions);
132132
};
133133

134+
vm.printInstance = function() {
135+
console.log('instance', vm.instance);
136+
};
137+
134138
}
135139

136140
angular

debug/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@
2626
</head>
2727
<body ng-app="AngularChartDebug" ng-controller="DebugController as debug">
2828

29-
<angular-chart options="debug.climateOptions"></angular-chart>
29+
<angular-chart options="debug.climateOptions" ></angular-chart>
3030
<button ng-click="debug.updateClimateDimension()">Change Dimension</button>
3131
Zoom: <input type="number" ng-model="debug.climateOptions.state.range[0]"> <input type="number" ng-model="debug.climateOptions.state.range[1]">
3232

3333

34-
<angular-chart options="debug.timestampOptions"></angular-chart>
34+
<angular-chart options="debug.timestampOptions" instance="debug.instance"></angular-chart>
35+
<button ng-click="debug.printInstance()">Print Instance</button>
3536
<button ng-click="debug.updateTimestampDimension()">Change Dimension</button>
3637
Zoom: {{debug.timestampOptions.state.range}}
3738

karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ module.exports = function (config) {
5252

5353
coverageReporter: {
5454
type: 'lcov', // lcov or lcovonly are required for generating lcov.info files
55+
subdir: '.',
5556
dir: 'coverage/'
5657
}
5758

src/js/controller.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
unwrapPromise();
1818
addIdentifier();
1919
addInlineStyle();
20-
chartService = AngularChartService.getInstance(configuration, $scope);
20+
getInstance();
2121
registerDestroyListener();
2222
}
2323

@@ -46,6 +46,11 @@
4646
angular.element($element).css('display', 'block');
4747
}
4848

49+
function getInstance() {
50+
chartService = AngularChartService.getInstance(configuration, $scope);
51+
$scope.instance = chartService.chart;
52+
}
53+
4954
/**
5055
* Remove all references when directive is destroyed
5156
*/

src/js/directive.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
return {
1717
restrict: 'EA',
1818
scope: {
19-
options: '='
19+
options: '=',
20+
instance: '=?'
2021
},
2122
controller: 'AngularChartController'
2223
};

src/js/service.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
/* istanbul ignore next */
88
var c3 = window.c3 ? window.c3 : 'undefined' !== typeof require ? require('c3') : undefined;
99

10-
function AngularChartService($timeout, AngularChartWatcher, AngularChartConverter, AngularChartState) {
10+
function AngularChartService($timeout, $q, AngularChartWatcher, AngularChartConverter, AngularChartState) {
1111

1212
var ChartService = function(baseConfig, scope) {
13-
this.chart = null;
13+
this.deferredChart = $q.defer();
14+
this.chart = this.deferredChart.promise;
1415
this.baseConfiguration = {};
1516
this.configuration = {};
1617
this.scopeReference = null;
@@ -70,8 +71,13 @@
7071
this.convertOptions();
7172
this.applyChartOptions();
7273
this.synchronizeState();
73-
this.generateChart();
74-
this.stateCallback();
74+
75+
// call long running generation async
76+
var chartService = this;
77+
$timeout(function() {
78+
chartService.generateChart(chartService);
79+
chartService.stateCallback();
80+
});
7581
};
7682

7783
/**
@@ -123,11 +129,15 @@
123129
/**
124130
* Render the chart.
125131
*/
126-
ChartService.prototype.generateChart = function() {
132+
ChartService.prototype.generateChart = function(chartService) {
127133
// TODO add own onresize listener?
128134
// TODO regenerate chart only one or two times per second
129135
// TODO evaluate if it makes sense to destroy the chart first
130-
this.chart = c3.generate(this.configuration);
136+
137+
var chart = c3.generate(chartService.configuration);
138+
chartService.deferredChart.resolve(chart);
139+
chartService.scopeReference.instance = chart;
140+
chartService.chart = chart;
131141
};
132142

133143
/**
@@ -142,7 +152,9 @@
142152
* Destroy the chart if one ist present.
143153
*/
144154
ChartService.prototype.destroyChart = function() {
145-
this.chart.destroy();
155+
if (this.chart.destroy) {
156+
this.chart.destroy();
157+
}
146158
};
147159

148160
ChartService.prototype.merge = angular.merge || deepMerge;

test/controller_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('Controller: AngularChartController', function() {
5959
});
6060

6161
// destroy
62-
it('should instantiate DirectiveCtrl.', function() {
62+
it('should destroy DirectiveCtrl.', function() {
6363
// setup
6464
$scope.options = {};
6565
var controller = setUpController();

0 commit comments

Comments
 (0)