Skip to content

Commit

Permalink
feat(instance): give access to the c3js API using the instance attrib…
Browse files Browse the repository at this point in the history
…ute on the directive
  • Loading branch information
maxklenk committed Mar 15, 2016
1 parent 45f640e commit 9ba150d
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 37 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,22 @@ angular
}
};

// optional (direct access to c3js API http://c3js.org/reference.html#api)
$scope.instance = null;

});
```

Then you are ready to use the directive in your view:
```html
<div ng-controller="Controller">
<angular-chart options="options"></angular-chart>
<angular-chart options="options" instance="instance"></angular-chart>
</div>
```

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

## API
## OPTIONS

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


## INSTANCE

The `instance` attribute of the directive will be filled with a promise on initialization.
The promise will be fulfilled the first time the chart is generated.
Every time a new chart instance is created the `instance` of the directive will be updated as well.

You can call all [c3js API calls](http://c3js.org/reference.html#api) such as `flow()`, `resize()`, ... on the chart instance.


## custom Style
The whole chart is based on SVG, which allows you to stlye most parts using CSS.
The documentation of c3.js provides a few [examples](http://c3js.org/examples.html#style) on how to style your chart.
Expand Down
38 changes: 28 additions & 10 deletions angular-chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
return {
restrict: 'EA',
scope: {
options: '='
options: '=',
instance: '=?'
},
controller: 'AngularChartController'
};
Expand Down Expand Up @@ -467,15 +468,16 @@
'use strict';

/* istanbul ignore next */
AngularChartService.$inject = ['$timeout', 'AngularChartWatcher', 'AngularChartConverter', 'AngularChartState'];
AngularChartService.$inject = ['$timeout', '$q', 'AngularChartWatcher', 'AngularChartConverter', 'AngularChartState'];
var angular = window.angular ? window.angular : 'undefined' !== typeof require ? require('angular') : undefined;
/* istanbul ignore next */
var c3 = window.c3 ? window.c3 : 'undefined' !== typeof require ? require('c3') : undefined;

function AngularChartService($timeout, AngularChartWatcher, AngularChartConverter, AngularChartState) {
function AngularChartService($timeout, $q, AngularChartWatcher, AngularChartConverter, AngularChartState) {

var ChartService = function(baseConfig, scope) {
this.chart = null;
this.deferredChart = $q.defer();
this.chart = this.deferredChart.promise;
this.baseConfiguration = {};
this.configuration = {};
this.scopeReference = null;
Expand Down Expand Up @@ -535,8 +537,13 @@
this.convertOptions();
this.applyChartOptions();
this.synchronizeState();
this.generateChart();
this.stateCallback();

// call long running generation async
var chartService = this;
$timeout(function() {
chartService.generateChart(chartService);
chartService.stateCallback();
});
};

/**
Expand Down Expand Up @@ -588,11 +595,15 @@
/**
* Render the chart.
*/
ChartService.prototype.generateChart = function() {
ChartService.prototype.generateChart = function(chartService) {
// TODO add own onresize listener?
// TODO regenerate chart only one or two times per second
// TODO evaluate if it makes sense to destroy the chart first
this.chart = c3.generate(this.configuration);

var chart = c3.generate(chartService.configuration);
chartService.deferredChart.resolve(chart);
chartService.scopeReference.instance = chart;
chartService.chart = chart;
};

/**
Expand All @@ -607,7 +618,9 @@
* Destroy the chart if one ist present.
*/
ChartService.prototype.destroyChart = function() {
this.chart.destroy();
if (this.chart.destroy) {
this.chart.destroy();
}
};

ChartService.prototype.merge = angular.merge || deepMerge;
Expand Down Expand Up @@ -851,7 +864,7 @@
unwrapPromise();
addIdentifier();
addInlineStyle();
chartService = AngularChartService.getInstance(configuration, $scope);
getInstance();
registerDestroyListener();
}

Expand Down Expand Up @@ -880,6 +893,11 @@
angular.element($element).css('display', 'block');
}

function getInstance() {
chartService = AngularChartService.getInstance(configuration, $scope);
$scope.instance = chartService.chart;
}

/**
* Remove all references when directive is destroyed
*/
Expand Down
2 changes: 1 addition & 1 deletion angular-chart.min.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions debug/debug-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@
console.log('new options', vm.timestampOptions);
};

vm.printInstance = function() {
console.log('instance', vm.instance);
};

}

angular
Expand Down
5 changes: 3 additions & 2 deletions debug/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
</head>
<body ng-app="AngularChartDebug" ng-controller="DebugController as debug">

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


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

Expand Down
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ module.exports = function (config) {

coverageReporter: {
type: 'lcov', // lcov or lcovonly are required for generating lcov.info files
subdir: '.',
dir: 'coverage/'
}

Expand Down
7 changes: 6 additions & 1 deletion src/js/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
unwrapPromise();
addIdentifier();
addInlineStyle();
chartService = AngularChartService.getInstance(configuration, $scope);
getInstance();
registerDestroyListener();
}

Expand Down Expand Up @@ -46,6 +46,11 @@
angular.element($element).css('display', 'block');
}

function getInstance() {
chartService = AngularChartService.getInstance(configuration, $scope);
$scope.instance = chartService.chart;
}

/**
* Remove all references when directive is destroyed
*/
Expand Down
3 changes: 2 additions & 1 deletion src/js/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
return {
restrict: 'EA',
scope: {
options: '='
options: '=',
instance: '=?'
},
controller: 'AngularChartController'
};
Expand Down
26 changes: 19 additions & 7 deletions src/js/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
/* istanbul ignore next */
var c3 = window.c3 ? window.c3 : 'undefined' !== typeof require ? require('c3') : undefined;

function AngularChartService($timeout, AngularChartWatcher, AngularChartConverter, AngularChartState) {
function AngularChartService($timeout, $q, AngularChartWatcher, AngularChartConverter, AngularChartState) {

var ChartService = function(baseConfig, scope) {
this.chart = null;
this.deferredChart = $q.defer();
this.chart = this.deferredChart.promise;
this.baseConfiguration = {};
this.configuration = {};
this.scopeReference = null;
Expand Down Expand Up @@ -70,8 +71,13 @@
this.convertOptions();
this.applyChartOptions();
this.synchronizeState();
this.generateChart();
this.stateCallback();

// call long running generation async
var chartService = this;
$timeout(function() {
chartService.generateChart(chartService);
chartService.stateCallback();
});
};

/**
Expand Down Expand Up @@ -123,11 +129,15 @@
/**
* Render the chart.
*/
ChartService.prototype.generateChart = function() {
ChartService.prototype.generateChart = function(chartService) {
// TODO add own onresize listener?
// TODO regenerate chart only one or two times per second
// TODO evaluate if it makes sense to destroy the chart first
this.chart = c3.generate(this.configuration);

var chart = c3.generate(chartService.configuration);
chartService.deferredChart.resolve(chart);
chartService.scopeReference.instance = chart;
chartService.chart = chart;
};

/**
Expand All @@ -142,7 +152,9 @@
* Destroy the chart if one ist present.
*/
ChartService.prototype.destroyChart = function() {
this.chart.destroy();
if (this.chart.destroy) {
this.chart.destroy();
}
};

ChartService.prototype.merge = angular.merge || deepMerge;
Expand Down
2 changes: 1 addition & 1 deletion test/controller_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('Controller: AngularChartController', function() {
});

// destroy
it('should instantiate DirectiveCtrl.', function() {
it('should destroy DirectiveCtrl.', function() {
// setup
$scope.options = {};
var controller = setUpController();
Expand Down
Loading

0 comments on commit 9ba150d

Please sign in to comment.