Cannot get react-chartjs to update - javascript

I am trying to follow the "Example usage" code from react-chartjs github page
I am new to javascript and react and probably just being naive. How can I get the new chartData from "_onChange" to update my PolarAreaChart? I tried something more direct by calling element.getDocumentById("polarChart"), but that returns nothing and then I cannot call .update on it... the whole "insert redraw in the xml" and it will magically call update seems magical to me :(
PolarPlot.jsx
var React = require ('react');
var PolarAreaChart = require ('react-chartjs').PolarArea;
var FilterStore = require ('FilterStore')
var PolarPlot = React.createClass ({
componentWillMount: function () {
FilterStore.addChangeListener (this._onChange);
},
_onChange: function () {
console.log("time to update")
chartData = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
}]
},
render: function () {
return (
<PolarAreaChart id="polarChart" data={chartData} options={chartOptions} redraw/>
);
}
});
var chartData = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
}
];
var chartOptions = [
{
//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop : true,
//String - The colour of the label backdrop
scaleBackdropColor : "rgba(255,255,255,0.75)",
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero : true,
//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY : 2,
//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX : 2,
//Boolean - Show line for each value in the scale
scaleShowLine : true,
//Boolean - Stroke a line around each segment in the chart
segmentShowStroke : true,
//String - The colour of the stroke on each segement.
segmentStrokeColor : "#fff",
//Number - The width of the stroke value in pixels
segmentStrokeWidth : 2,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect.
animationEasing : "easeOutBounce",
//Boolean - Whether to animate the rotation of the chart
animateRotate : true,
//Boolean - Whether to animate scaling the chart from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
}
];
module.exports = PolarPlot;

Your PolarPlot component is not rendered unless you explicitly change the state. Your chartData is not part of the component state. So assigning a new array to that variable does nothing more than that. Move this chartData to the component state. Then, whenever you update this state variable you are going to force the re-render. Something like this:
var PolarPlot = React.createClass ({
componentWillMount: function () {
FilterStore.addChangeListener (this._onChange);
},
getInitialState: function() {
return {chartData: chartData};
},
_onChange: function () {
console.log("time to update")
this.setState({
chartData: [{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
}]
});
},
render: function () {
return (
<PolarAreaChart id="polarChart" data={this.state.chartData} options={chartOptions} redraw/>
);
}
});
If you want to know more about how components rendering reacts to state changes check Reactive state section from the React Tutorial.

Related

Chartist .SVG Alignment/Padding

I generate a Chartist Pie chart with the following data:
var mapPieData = {
series: [
{ value: 578, className: "pieNegativeColour", label: "online" },
{ value: 3182, className: "piePositiveColour", label: "offline" }
],
highest: { label: "Huawei", value: "10258", className: "pieColour1" },
maximum: 3760};
I use the following options to configure it:
var mapPieOptions = {
showLabel: true,
fullWidth: true,
chartPadding: 0};
I have to overlay the generated Pie chart on an .SVG map.
The problem is that the generated Pie chart is centred inside an .SVG container that's wider than it needs to be. That means the positioning is impractical. If I position the Pie chart on the top left, it actually ends up in the top middle, which is not what I want.
I want to remove this extra space around the Pie chart.
I was able to recreate your pie chart with your supplied code on the website with the example fiddles.
http://gionkunz.github.io/chartist-js/examples.html
$('.ct-chart').css({'background-color':'white'});
var data = {
series: [
{ value: 578, className: "ct-series-c", label: "online" },
{ value: 3182, className: "ct-series-a", label: "offline" }
],
highest: { label: "Huawei", value: "10258", className: "pieColour1" },
maximum: 3760
};
var options = {
showLabel: true,
fullWidth: true,
chartPadding: 0
};
new Chartist.Pie('.ct-chart', data, options);
I analyzed this and noticed that if I set the padding to a negative value, the render would increase in size, but would get clipped.
var options = {
showLabel: true,
fullWidth: true,
chartPadding: -40
};
Then I increased the size of the containing element, which sat at 100%, but actually didn't take up the full height.
By setting the container element to 750px height(as wide as it broad it would take up the full width of the element.
So now we have to automate this.
Assuming you have jQuery on hand you can simply do:
var $chart = $('.ct-chart');
$chart.css({'height':$chart.width()+'px'});
Running example on the snippets site:
var $chart = $('.ct-chart');
$chart.css({'background-color':'white','height':$chart.width()+'px'});
var data = {
series: [
{ value: 578, className: "ct-series-c", label: "online" },
{ value: 3182, className: "ct-series-a", label: "offline" }
],
highest: { label: "Huawei", value: "10258", className: "pieColour1" },
maximum: 3760
};
var options = {
showLabel: true,
fullWidth: true,
chartPadding: 0
};
new Chartist.Pie('.ct-chart', data, options);
If you don't have jQuery replace the jQuery lines with:
var chart = document.querySelector('#pie-with-custom-labels .ct-chart');
chart.style.height = chart.clientWidth+"px";

Saving pie chart as an image using database data

Require some help when trying to save chart as an image. Sorry just started this new chart.js.
Issue:
How do I add my database data inside the chart? I keep try to add in $user but it keep giving me undefined user.
Here is the data that I want to add in from my database,
$users = DB::table('personal_infos')
->join('evaluations','evaluations.user_id', '=', 'personal_infos.id')
->select('evaluations.recommendation','evaluations.created_at' )
->where('evaluations.recommendation', '=', 'Yes')
->get();
For now I just used something like this to generate the pie chart:
<script type="text/javascript">
$("#save-btn").click(function() {
$("#canvas").get(0).toBlob(function(blob) {
saveAs(blob, "chart_1.png");
});
});
var data = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
}
];
var ctx = $("#canvas").get(0).getContext("2d");
var mychart = new Chart(ctx).Pie(data,
{
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : false,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 2,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout : 0, // This is 0 for Pie charts
//Number - Amount of animation steps
animationSteps : 10,
//String - Animation easing effect
animationEasing : "linear",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
}
);
</script>

How to customize annotation's layout in HighCharts

I have been using HighCharts extensively for one of my project. Recently I started using Annotation.js along with it.
ALthough, the library works well but I can't configure its usage at all. The link here provides options but they are not working for me
My issues:
I have multiple charts on a page. As soon as I use annotation.js , each of them shows annotation. how do I show them on desired charts. I tried
annotations :[{ enabledButtons : false}]
and
annotationOptions :{ enabledButtons : false}
Both of them had no affect.
2.I want to display the pallette (containing icons like square, circle etc..) at top-right.
I used xValue, yValue attribute,
I used x, y attribute,
I used 'anchorX and anchorY` attribute.
None of the above works for me.
I want just to show the text icon. How can I hide other icons (line, square and circle). Didn't get any way to try for this one.
Am I missing something here. Kindly suggest. My basic way of using chart config is as below:
chart: {
type: chartData.Type.toLowerCase()
//annotations: [],
},
annotationsOptions: {
xValue: 234,
yValue:12
},
title: {
text: chartData.xTitle ? chartData.xTitle : ""
},
xAxis: {
categories: chartData.Categories
},
yAxis: {
allowDecimals: false,
min: 0,
title: {
text: chartData.yTitle ? chartData.yTitle : ""
},
plotLines: [{
value: 0,
width: 1,
color: "#808080"
}]
},
annotations: [{
xValue: 40,
yValue: 15
}],
plotOptions: {
line: {
marker: {
enabled: true
}
}
},
series: chartData['Series'][opt] ? chartData['Series'][opt] : chartData['Series'][opt.replace(/-|\s/g, "")],
}
I have tried annotations inside charts object as well.
You should be able to hide annotations buttons using:
annotationsOptions: {
enabledButtons: false
},
You can use annotationsOptions.buttons for changing the buttons you would like to display. Here you can see the code that will show only text butotn:
annotationsOptions: {
buttons: [{
annotationEvents: {
step: function() {}, // to be called during mouse drag for new annotation
stop: function(e) {
var ann = this,
chart = ann.chart,
index = chart.annotationInputIndex = chart.annotationInputIndex ? chart.annotationInputIndex : 1,
input = document.createElement('span'),
button;
input.innerHTML = '<input type="text" class="annotation-' + index + '" placeholder="Add text"><button class=""> Done </button>';
input.style.position = 'absolute';
input.style.left = e.pageX + 'px';
input.style.top = e.pageY + 'px';
document.body.appendChild(input);
input.querySelectorAll('input')[0].focus();
button = input.querySelectorAll('button')[0];
button.onclick = function() {
var parent = this.parentNode;
ann.update({
title: {
text: parent.querySelectorAll('input')[0].value
}
});
parent.parentNode.removeChild(parent);
};
chart.annotationInputIndex++;
} // to be called after mouse up / release
},
annotation: { // standard annotation options, used for new annotation
anchorX: 'left',
anchorY: 'top',
xAxis: 0,
yAxis: 0,
shape: {
// type: 'text'
}
},
symbol: { // button symbol options
shape: 'text', // shape, taken from Highcharts.symbols
size: 12,
style: {
'stroke-width': 2,
'stroke': 'black',
fill: 'red',
zIndex: 121
}
},
style: { // buton style itself
fill: 'black',
stroke: 'blue',
strokeWidth: 2,
},
size: 12, // buton size
states: { // states for button
selected: {
fill: '#9BD'
},
hover: {
fill: '#9BD'
}
}
}]
}
Here you can find an example how it may work: http://jsfiddle.net/7m3Mr/261/
You can move your buttons using:
annotationsOptions: {
buttonsOffsets: [0, -50],
},
Here you can find demo showing how it may work:
http://jsfiddle.net/7m3Mr/263/

angular chart pie-chart data click event

Angular JS chart is awesome, But i need to implement click event in the piechart which i have created.. Here is the coding..
This is the JavaScript Coding...
$scope.pied = [{
value: 4,
color: "#FF5A5E",
highlight: "#FF5A5E",
label: "Prospective"
}, {
value: 0,
color: "#46BFBD",
highlight: "#46BFBD",
label: "Pending"
}, {
value: 0,
color: "#FDB45C",
highlight: "#FDB45C",
label: "CallBacks"
}, {
value: 4,
color: "#e6e6fa",
highlight: "#e6e6fa",
label: "FollowUp"
}, {
value: 1,
color: "#cc5229",
highlight: "#cc5229",
label: "Not Interested"
}, {
value: 0,
color: "#556b2f",
highlight: "#556b2f",
label: "Close"
}]
var pieOptions = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke: true,
//String - The colour of each segment stroke
segmentStrokeColor: "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth: 2,
//Boolean - Whether we should animate the chart
animation: true,
//Number - Amount of animation steps
animationSteps: 100,
//String - Animation easing effect
animationEasing: "easeOutBounce",
//Boolean - Whether we animate the rotation of the Pie
animateRotate: true,
//Boolean - Whether we animate scaling the Pie from the centre
animateScale: false,
//Function - Will fire on animation completion.
onAnimationComplete: null
}
var ctx = document.getElementById("pieChart").getContext("2d");
var myPieChart = new Chart(ctx).Pie($scope.pied, pieOptions);
ctx.onclick = function(evt){
var activePoints = myPieChart.getPointsAtEvent(evt);
console.log("active: "+activePoints);
// => activePoints is an array of points on the canvas that are at the same position as the click event.
};
document.getElementById('js-legend').innerHTML = myPieChart.generateLegend();
This is the HTML Coding..
<canvas id="pieChart" width="440" height="200" ></canvas>
<div id="js-legend" class="chart-legend"></div>
This is the image of the above program.. i have wrote coding that when i click on The FollowUP it must the datas related to it.. But the click event is not working..??
Please see to the above code and picture and guide me to get the exact output what i expect. Thanks in advance guys...
I have Used angular-chart.js instead this chart.js Angular JS Documentation is here . Angular Chart is little bit easy than chart.js..
Thanks for the support guys.. :)

Embed unique identifier in Chart.js segments?

I want to make my pie-chart interactive by allowing the user to double-click on a slice to drill down. I believe that the way to do this is to create an onclick handler on the canvas, and use getSegmentsAtEvent() to determine which slice was clicked.
The segment data returned by the call to getSegmentsAtEvent() is possibly ambiguous though. Here is a sample of the returned data:
[{
"circumference": 4.1887902047863905,
"endAngle": 8.901179185171081,
"fillColor": "#FF5A5E",
"highlightColor": "#FF5A5E",
"innerRadius": 0,
"label": "Red",
"outerRadius": 99.5,
"showStroke": true,
"startAngle": 4.71238898038469,
"strokeColor": "#fff",
"strokeWidth": 2,
"value": 300
}]
Of those fields, only value, fillColor, highlightColor, and label are supplied by me, and none of them are necessarily unique. I could ensure that label is unique, but that might make it less readable for humans.
I have tried adding an additional property (e.g. "id") into the data I pass into Pie(), but it is stripped out when I get the segment data back from this call. Is there a way to add a property to each segment which I can use to positively identify them, without overloading the label field?
You would need to either override the pie chart or create a new chart type that inherits from pie.
Here is an example of a new chart type, i have passed a new attribute called id and then the only thing that needs to be different in this chart is that when the data is being added this id needs to passed to the chart
Chart.types.Pie.extend({
name: "PieUnique",
addData: function (segment, atIndex, silent) {
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value: segment.value,
outerRadius: (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
fillColor: segment.color,
highlightColor: segment.highlight || segment.color,
showStroke: this.options.segmentShowStroke,
strokeWidth: this.options.segmentStrokeWidth,
strokeColor: this.options.segmentStrokeColor,
startAngle: Math.PI * this.options.startAngle,
circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label: segment.label,
//add option passed
id: segment.id
}));
if (!silent) {
this.reflow();
this.update();
}
},
});
var pieData = [{
value: 300,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Red",
id: "1-upi"
}, {
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green",
id: "2-upi"
}, {
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow",
id: "3-upi"
}, {
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey",
id: "4-upi"
}, {
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey",
id: "5-upi"
}
];
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPie = new Chart(ctx).PieUnique(pieData);
document.getElementById("chart-area").onclick = function (evt) {
var activePoints = window.myPie.getSegmentsAtEvent(evt);
//you can now access the id at activePoints[0].id
console.log(activePoints);
};
<script src="https://raw.githack.com/leighquince/Chart.js/master/Chart.js"></script>
<canvas id="chart-area" width="400"></canvas>
To get an slice that was clicked on, getElementAtEvent can be used. Worked for me!
stackedBar(datasets) {
var c = $("#canvas-bar");
var ctx = c[0].getContext("2d");
let __this = this;
this.chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["something"],
datasets: datasets,
},
options: {
onClick: function (e, item) {
__this.onClickAction(e, item);
},
title: {},
legend: {},
scales: {}
}
});
}
onClickAction(event, elements) {
if (elements && elements.length) {
let selected = this.chart.getElementAtEvent(event)[0];
let sliceIndex = selected['_datasetIndex'];
}
}

Categories

Resources