react-chartjs
Version:
react charting components using the chartjs lib
150 lines (132 loc) • 5.08 kB
JavaScript
var React = require('react');
var createReactClass = require('create-react-class');
var ReactDOM = require('react-dom');
module.exports = {
createClass: function(chartType, methodNames, dataKey) {
var excludedProps = ['data', 'options', 'redraw'];
var classData = {
displayName: chartType + 'Chart',
getInitialState: function() { return {}; },
render: function() {
var _props = {
ref: 'canvass'
};
for (var name in this.props) {
if (this.props.hasOwnProperty(name)) {
if (excludedProps.indexOf(name) === -1) {
_props[name] = this.props[name];
}
}
}
return React.createElement('canvas', _props);
}
};
var extras = ['clear', 'stop', 'resize', 'toBase64Image', 'generateLegend', 'update', 'addData', 'removeData'];
function extra(type) {
classData[type] = function() {
return this.state.chart[type].apply(this.state.chart, arguments);
};
}
classData.componentDidMount = function() {
this.initializeChart(this.props);
};
classData.componentWillUnmount = function() {
var chart = this.state.chart;
chart.destroy();
};
classData.componentWillReceiveProps = function(nextProps) {
var chart = this.state.chart;
if (nextProps.redraw) {
chart.destroy();
this.initializeChart(nextProps);
} else {
dataKey = dataKey || dataKeys[chart.name];
updatePoints(nextProps, chart, dataKey);
if (chart.scale) {
chart.scale.xLabels = nextProps.data.labels;
if (chart.scale.calculateXLabelRotation){
chart.scale.calculateXLabelRotation();
}
}
chart.update();
}
};
classData.initializeChart = function(nextProps) {
var Chart = require('chart.js');
var el = ReactDOM.findDOMNode(this);
var ctx = el.getContext("2d");
var chart = new Chart(ctx)[chartType](nextProps.data, nextProps.options || {});
this.state.chart = chart;
};
// return the chartjs instance
classData.getChart = function() {
return this.state.chart;
};
// return the canvass element that contains the chart
classData.getCanvass = function() {
return this.refs.canvass;
};
classData.getCanvas = classData.getCanvass;
var i;
for (i=0; i<extras.length; i++) {
extra(extras[i]);
}
for (i=0; i<methodNames.length; i++) {
extra(methodNames[i]);
}
return createReactClass(classData);
}
};
var dataKeys = {
'Line': 'points',
'Radar': 'points',
'Bar': 'bars'
};
var updatePoints = function(nextProps, chart, dataKey) {
var name = chart.name;
if (name === 'PolarArea' || name === 'Pie' || name === 'Doughnut') {
nextProps.data.forEach(function(segment, segmentIndex) {
if (!chart.segments[segmentIndex]) {
chart.addData(segment);
} else {
Object.keys(segment).forEach(function (key) {
chart.segments[segmentIndex][key] = segment[key];
});
}
});
while(nextProps.data.length < chart.segments.length) {
chart.removeData();
}
} else if (name === "Radar") {
chart.removeData();
nextProps.data.datasets.forEach(function(set, setIndex) {
set.data.forEach(function(val, pointIndex) {
if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
addData(nextProps, chart, setIndex, pointIndex);
} else {
chart.datasets[setIndex][dataKey][pointIndex].value = val;
}
});
});
} else {
while (chart.scale.xLabels.length > nextProps.data.labels.length) {
chart.removeData();
}
nextProps.data.datasets.forEach(function(set, setIndex) {
set.data.forEach(function(val, pointIndex) {
if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
addData(nextProps, chart, setIndex, pointIndex);
} else {
chart.datasets[setIndex][dataKey][pointIndex].value = val;
}
});
});
}
};
var addData = function(nextProps, chart, setIndex, pointIndex) {
var values = [];
nextProps.data.datasets.forEach(function(set) {
values.push(set.data[pointIndex]);
});
chart.addData(values, nextProps.data.labels[setIndex]);
};