diff --git a/README.md b/README.md
index b43718a..e36ecc2 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ angular.module('MyModule', ['amChartsDirective'])
```
-#### [You can play with a working JS Fiddle example here!](http://jsfiddle.net/w3vpc35o/41/)
+#### [JSFiddle Example here](http://jsfiddle.net/w3vpc35o/41/)
#### Quick sample code
@@ -84,6 +84,77 @@ $scope.amChartOptions = {
}]
}
```
+
+#### Promise based chart rendering
+
+``` javascript
+
+// this function returns our chart data as a promise
+ $scope.dataFromPromise = function(){
+ var deferred = $q.defer();
+
+ var data = [{
+ year: 2005,
+ income: 23.5,
+ expenses: 18.1
+ }, {
+ year: 2006,
+ income: 26.2,
+ expenses: 22.8
+ }, {
+ year: 2007,
+ income: 30.1,
+ expenses: 23.9
+ }, {
+ year: 2008,
+ income: 29.5,
+ expenses: 25.1
+ }, {
+ year: 2009,
+ income: 24.6,
+ expenses: 25
+ }];
+
+ deferred.resolve(data)
+ return deferred.promise;
+ };
+
+ // We can optionally pass a promise to the options attribute on the AmChartsDirective
+ // to delay the chart rendering until the promise resolves
+ $scope.amChartOptions = $timeout(function(){
+ return {
+ // we can also use a promise for the data property to delay the rendering of
+ // the chart till we actually have data
+ data: $scope.dataFromPromise(),
+ type: "serial",
+ theme: 'black',
+ categoryField: "year",
+ rotate: true,
+ pathToImages: 'https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/images/',
+ legend: {
+ enabled: true
+ },
+ chartScrollbar: {
+ enabled: true,
+ },
+ categoryAxis: {
+ gridPosition: "start",
+ parseDates: false
+ },
+ valueAxes: [{
+ position: "top",
+ title: "Million USD"
+ }],
+ graphs: [{
+ type: "column",
+ title: "Income",
+ valueField: "income",
+ fillAlphas: 1,
+ }]
+ }
+ }, 1000)
+
+```
##### If you do not specify a category field or a value field, the directive will assume the category field is at index [0] and the value field is at index [1]. Using the example above, 'year' would be the category field, and 'income' would be the value field.
diff --git a/dist/amChartsDirective.js b/dist/amChartsDirective.js
index 058731b..ebdc8be 100644
--- a/dist/amChartsDirective.js
+++ b/dist/amChartsDirective.js
@@ -18,218 +18,230 @@ angular.module('amChartsDirective', []).directive('amChart', ['$q', function ($q
$el.attr('id', id);
var chart;
- // we can't render a chart without any data
- if ($scope.options.data) {
- var renderChart = function (amChartOptions) {
- var o = amChartOptions || $scope.options;
-
- // set height and width
- var height = $scope.height || '100%';
- var width = $scope.width || '100%';
-
- $el.css({
- 'height': height,
- 'width': width
- });
+ // allow $scope.options to be a promise
+ $q.when($scope.options).then(function(options){
+ // we can't render a chart without any data
+ if (options.data) {
+ var renderChart = function (amChartOptions) {
+ var o = amChartOptions || options;
+
+ // set height and width
+ var height = $scope.height || '100%';
+ var width = $scope.width || '100%';
+
+ $el.css({
+ 'height': height,
+ 'width': width
+ });
- // instantiate new chart object
- if (o.type === 'xy') {
- chart = o.theme ? new AmCharts.AmXYChart(AmCharts.themes[o.theme]) : new AmCharts.AmXYChart();
- } else if (o.type === 'pie') {
- chart = o.theme ? new AmCharts.AmPieChart(AmCharts.themes[o.theme]) : new AmCharts.AmPieChart();
- } else {
- chart = o.theme ? new AmCharts.AmSerialChart(AmCharts.themes[o.theme]) : new AmCharts.AmSerialChart();
- }
+ // instantiate new chart object
+ if (o.type === 'xy') {
+ chart = o.theme ? new AmCharts.AmXYChart(AmCharts.themes[o.theme]) : new AmCharts.AmXYChart();
+ } else if (o.type === 'pie') {
+ chart = o.theme ? new AmCharts.AmPieChart(AmCharts.themes[o.theme]) : new AmCharts.AmPieChart();
+ } else if (o.type === 'funnel') {
+ chart = o.theme ? new AmCharts.AmFunnelChart(AmCharts.themes[o.theme]) : new AmCharts.AmFunnelChart();
+ } else if (o.type === 'radar') {
+ chart = o.theme ? new AmCharts.AmRadarChart(AmCharts.themes[o.theme]) : new AmCharts.AmRadarChart();
+ } else {
+ chart = o.theme ? new AmCharts.AmSerialChart(AmCharts.themes[o.theme]) : new AmCharts.AmSerialChart();
+ }
+
+ /** set some default values that amCharts doesnt provide **/
+ $q.when(o.data)
+ .then(function (data) {
+
+ chart.dataProvider = data;
+ // if a category field is not specified, attempt to use the first field from an object in the array
+ chart.categoryField = o.categoryField || Object.keys(o.data[0])[0];
+ chart.startDuration = 0.5; // default animation length, because everyone loves a little pizazz
+
+ // AutoMargin is on by default, but the default 20px all around seems to create unnecessary white space around the control
+ chart.autoMargins = true;
+ chart.marginTop = 0;
+ chart.marginLeft = 0;
+ chart.marginBottom = 0;
+ chart.marginRight = 0;
+
+ // modify default creditsPosition
+ chart.creditsPosition = 'top-right';
+
+ var chartKeys = Object.keys(o);
+ for (var i = 0; i < chartKeys.length; i++) {
+ if (typeof o[chartKeys[i]] !== 'object' && typeof o[chartKeys[i]] !== 'function') {
+ chart[chartKeys[i]] = o[chartKeys[i]];
+ }
+ }
- /** set some default values that amCharts doesnt provide **/
- $q.when(o.data)
- .then(function (data) {
+ function generateGraphProperties(data) {
+ // Assign Category Axis Properties
+ if (o.categoryAxis) {
+ var categoryAxis = chart.categoryAxis;
+
+ if (categoryAxis) {
+ /* if we need to create any default values, we should assign them here */
+ categoryAxis.parseDates = true;
+
+ var keys = Object.keys(o.categoryAxis);
+ for (var i = 0; i < keys.length; i++) {
+ if (!angular.isObject(o.categoryAxis[keys[i]]) || angular.isArray(o.categoryAxis[keys[i]])) {
+ categoryAxis[keys[i]] = o.categoryAxis[keys[i]];
+ } else {
+ console.log('Stripped categoryAxis obj ' + keys[i]);
+ }
+ }
+ chart.categoryAxis = categoryAxis;
+ }
+ }
- chart.dataProvider = data;
- // if a category field is not specified, attempt to use the first field from an object in the array
- chart.categoryField = o.categoryField || Object.keys(o.data[0])[0];
- chart.startDuration = 0.5; // default animation length, because everyone loves a little pizazz
-
- // AutoMargin is on by default, but the default 20px all around seems to create unnecessary white space around the control
- chart.autoMargins = true;
- chart.marginTop = 0;
- chart.marginLeft = 0;
- chart.marginBottom = 0;
- chart.marginRight = 0;
-
- // modify default creditsPosition
- chart.creditsPosition = 'top-right';
-
- var chartKeys = Object.keys(o);
- for (var i = 0; i < chartKeys.length; i++) {
- if (typeof o[chartKeys[i]] !== 'object' && typeof o[chartKeys[i]] !== 'function') {
- chart[chartKeys[i]] = o[chartKeys[i]];
- }
- }
+ // Create value axis
- function generateGraphProperties(data) {
- // Assign Category Axis Properties
- if (o.categoryAxis) {
- var categoryAxis = chart.categoryAxis;
+ /* if we need to create any default values, we should assign them here */
- if (categoryAxis) {
- /* if we need to create any default values, we should assign them here */
- categoryAxis.parseDates = true;
+ var addValueAxis = function (a) {
+ var valueAxis = new AmCharts.ValueAxis();
- var keys = Object.keys(o.categoryAxis);
+ var keys = Object.keys(a);
for (var i = 0; i < keys.length; i++) {
- if (!angular.isObject(o.categoryAxis[keys[i]]) || angular.isArray(o.categoryAxis[keys[i]])) {
- categoryAxis[keys[i]] = o.categoryAxis[keys[i]];
- } else {
- console.log('Stripped categoryAxis obj ' + keys[i]);
+ if (typeof a[keys[i]] !== 'object') {
+ valueAxis[keys[i]] = a[keys[i]];
}
}
- chart.categoryAxis = categoryAxis;
- }
- }
+ chart.addValueAxis(valueAxis);
+ };
- // Create value axis
+ if (o.valueAxes && o.valueAxes.length > 0) {
+ for (var i = 0; i < o.valueAxes.length; i++) {
+ addValueAxis(o.valueAxes[i]);
+ }
+ }
- /* if we need to create any default values, we should assign them here */
- var addValueAxis = function (a) {
- var valueAxis = new AmCharts.ValueAxis();
+ //reusable function to create graph
+ var addGraph = function (g) {
+ var graph = new AmCharts.AmGraph();
+ /** set some default values that amCharts doesnt provide **/
+ // if a category field is not specified, attempt to use the second field from an object in the array as a default value
+ graph.valueField = g.valueField || Object.keys(o.data[0])[1];
+ graph.balloonText = '[[category]]: [[value]]';
+ if (g) {
+ var keys = Object.keys(g);
+ // iterate over all of the properties in the graph object and apply them to the new AmGraph
+ for (var i = 0; i < keys.length; i++) {
+ graph[keys[i]] = g[keys[i]];
+ }
+ }
+ chart.addGraph(graph);
+ };
- var keys = Object.keys(a);
- for (var i = 0; i < keys.length; i++) {
- if (typeof a[keys[i]] !== 'object') {
- valueAxis[keys[i]] = a[keys[i]];
+ // create the graphs
+ if (o.graphs && o.graphs.length > 0) {
+ for (var i = 0; i < o.graphs.length; i++) {
+ addGraph(o.graphs[i]);
}
+ } else {
+ addGraph();
}
- chart.addValueAxis(valueAxis);
- };
- if (o.valueAxes && o.valueAxes.length > 0) {
- for (var i = 0; i < o.valueAxes.length; i++) {
- addValueAxis(o.valueAxes[i]);
+ var chartCursor = new AmCharts.ChartCursor();
+ if (o.chartCursor) {
+ var keys = Object.keys(o.chartCursor);
+ for (var i = 0; i < keys.length; i++) {
+ if (typeof o.chartCursor[keys[i]] !== 'object') {
+ chartCursor[keys[i]] = o.chartCursor[keys[i]];
+ }
+ }
}
- }
+ chart.addChartCursor(chartCursor);
-
- //reusable function to create graph
- var addGraph = function (g) {
- var graph = new AmCharts.AmGraph();
- /** set some default values that amCharts doesnt provide **/
- // if a category field is not specified, attempt to use the second field from an object in the array as a default value
- graph.valueField = g.valueField || Object.keys(o.data[0])[1];
- graph.balloonText = '[[category]]: [[value]]';
- if (g) {
- var keys = Object.keys(g);
- // iterate over all of the properties in the graph object and apply them to the new AmGraph
+ if (o.chartScrollbar) {
+ var scrollbar = new AmCharts.ChartScrollbar();
+ var keys = Object.keys(o.chartScrollbar);
for (var i = 0; i < keys.length; i++) {
- graph[keys[i]] = g[keys[i]];
+ scrollbar[keys[i]] = o.chartScrollbar[keys[i]];
}
+ chart.chartScrollbar = scrollbar;
}
- chart.addGraph(graph);
- };
- // create the graphs
- if (o.graphs && o.graphs.length > 0) {
- for (var i = 0; i < o.graphs.length; i++) {
- addGraph(o.graphs[i]);
+ if (o.balloon) {
+ chart.balloon = o.balloon;
}
- } else {
- addGraph();
}
- var chartCursor = new AmCharts.ChartCursor();
- if (o.chartCursor) {
- var keys = Object.keys(o.chartCursor);
- for (var i = 0; i < keys.length; i++) {
- if (typeof o.chartCursor[keys[i]] !== 'object') {
- chartCursor[keys[i]] = o.chartCursor[keys[i]];
- }
+ function generatePieProperties() {
+ if (o.balloon) {
+ chart.balloon = o.balloon;
}
}
- chart.addChartCursor(chartCursor);
- if (o.chartScrollbar) {
- var scrollbar = new AmCharts.ChartScrollbar();
- var keys = Object.keys(o.chartScrollbar);
+ if (o.legend) {
+ var legend = new AmCharts.AmLegend();
+ var keys = Object.keys(o.legend);
for (var i = 0; i < keys.length; i++) {
- scrollbar[keys[i]] = o.chartScrollbar[keys[i]];
+ legend[keys[i]] = o.legend[keys[i]];
}
- chart.chartScrollbar = scrollbar;
+ chart.legend = legend;
}
- if (o.balloon) {
- chart.balloon = o.balloon;
+ if (o.type === 'pie') {
+ generatePieProperties();
+ } else {
+ generateGraphProperties();
}
- }
- function generatePieProperties() {
- if (o.balloon) {
- chart.balloon = o.balloon;
+ if (o.titles) {
+ for (var i = 0;i < o.titles.length;i++) {
+ var title = o.titles[i];
+ chart.addTitle(title.text, title.size, title.color, title.alpha, title.bold);
+ };
}
- }
- if (o.legend) {
- var legend = new AmCharts.AmLegend();
- var keys = Object.keys(o.legend);
- for (var i = 0; i < keys.length; i++) {
- legend[keys[i]] = o.legend[keys[i]];
+ if(o.export) {
+ chart.export = o.export;
}
- chart.legend = legend;
- }
-
- if (o.type === 'pie') {
- generatePieProperties();
- } else {
- generateGraphProperties();
- }
- if (o.titles) {
- for (var i = 0;i < o.titles.length;i++) {
- var title = o.titles[i];
- chart.addTitle(title.text, title.size, title.color, title.alpha, title.bold);
- };
- }
+ // WRITE
+ chart.write(id);
- // WRITE
- chart.write(id);
+ });
+ }; //renderchart
- });
- }; //renderchart
+ // Render the chart
+ renderChart();
- // Render the chart
- renderChart();
+ // EVENTS =========================================================================
- // EVENTS =========================================================================
+ $scope.$on('amCharts.triggerChartAnimate', function (event, id) {
+ if (id === $el[0].id || !id) {
+ chart.animateAgain();
+ }
+ });
- $scope.$on('amCharts.triggerChartAnimate', function (event, id) {
- if (id === $el[0].id || !id) {
- chart.animateAgain();
- }
- });
+ $scope.$on('amCharts.updateData', function (event, data, id) {
+ if (id === $el[0].id || !id) {
+ chart.dataProvider = data;
+ chart.validateData();
+ }
- $scope.$on('amCharts.updateData', function (event, data, id) {
- if (id === $el[0].id || !id) {
- chart.dataProvider = data;
- chart.validateData();
- }
+ });
- });
+ $scope.$on('amCharts.validateNow', function (event, validateData, skipEvents, id) {
+ if (id === $el[0].id || !id) {
+ chart.validateNow(validateData === undefined ? true : validateData,
+ skipEvents === undefined ? false : skipEvents);
+ }
+ });
- $scope.$on('amCharts.validateNow', function (event, validateData, skipEvents, id) {
- if (id === $el[0].id || !id) {
- chart.validateNow(validateData === undefined ? true : validateData,
- skipEvents === undefined ? false : skipEvents);
- }
- });
+ $scope.$on('amCharts.renderChart', function (event, amChartOptions, id) {
+ if (id === $el[0].id || !id) {
+ renderChart(amChartOptions);
+ }
+ });
+ }
+ });
- $scope.$on('amCharts.renderChart', function (event, amChartOptions, id) {
- if (id === $el[0].id || !id) {
- renderChart(amChartOptions);
- }
- });
- }
}
};
}]);