getting error "c3" is not defined no-undef - javascript

I'm trying to write a custom bar chart directive in angular js using ES6. I have installed the c3 library using bower install c3 --save. when I run gulp serve I'm getting the error "c3" is not defined no-undef. Below is my code -
export class MyDirective {
constructor($interval) {
'ngInject';
this.template = '<div id=chart></div>';
this.restrict = 'E';
this.scope = {}
this.$interval = $interval;
}
compile(tElement) {
tElement.css('position', 'absolute');
}
link(scope, element) {
this.$interval(() => this.chart(), 1000);
}
chart() {
c3.generate({
bindto: '#chart',
data:{
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
}
}

If you install c3 directly, it will not be "angular friendly". I use c3 in my project with es2015 (and a babel transpire) and I choose to use c3-angular
To install it:
bower install c3-angular --save
And to import it as a dependency :
import 'c3-angular';
let barChartModule = angular.module('barChart', ['gridshore.c3js.chart']);
If you do this, you can define charts in your view this it is explained in the examples here

Related

ng2-google-charts component is undefined

I'm using ng2-google-charts with Ionic 6. I'm trying to redraw the gauge chart once the data is updated.
Here is the code that I'm using:
showGauge(value: number) {
this.gaugeChart = {
chartType: GoogleChartType.Gauge,
dataTable: [
['PSI', Number(value.toFixed(2))]
],
firstRowIsData: true,
options: {
height: 300,
max: 175,
chartArea: { height: '200' }
},
};
let c = this.gaugeChart.component;
c.draw();
}
But I get the following error, which indicates that the chart component is undefined. How can I solve this and redraw the chart?
Here's the error:
Error

Highcharts Gauge not showing in Angular

I am using Angular and Higcharts to visualize some data. I have gotten many of the other Highchart components working, now I want to use the gauges. I went to the Highcharts website and used the example at their demo section. Unfortunately this is not working.
For some reason the gauge is blank but the other parts of my component shows up. Example below:
My code looks like this:
TS file
import { Component, OnInit } from '#angular/core';
import * as Highcharts from 'highcharts';
#Component({
selector: 'app-speedo',
templateUrl: './speedo.component.html',
styleUrls: ['./speedo.component.scss']
})
export class SpeedoComponent implements OnInit {
chartOptions: any;
Highcharts: typeof Highcharts = Highcharts;
chartRef: Highcharts.Chart;
updateFromInput = false;
constructor() { }
ngOnInit(): void {
this.myChart();
}
chartCallback: Highcharts.ChartCallbackFunction = (chart) => {
this.chartRef = chart;
};
myChart(){
this.chartOptions = {
chart: {
type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '85%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor:
Highcharts.defaultOptions.legend.backgroundColor || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
exporting: {
enabled: false
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.1, '#55BF3B'], // green
[0.5, '#DDDF0D'], // yellow
[0.9, '#DF5353'] // red
],
lineWidth: 0,
tickWidth: 0,
minorTickInterval: null,
tickAmount: 2,
title: {
y: -70
},
labels: {
y: 16
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: 5,
borderWidth: 0,
useHTML: true
}
}
}
}
setTimeout(() => {
window.dispatchEvent(
new Event('resize')
);
}, 300);
}
}
HTML file
<p>speedo works!</p>
<highcharts-chart
[Highcharts]="Highcharts"
[options]="chartOptions"
style="width: 100%; height: 400px; display: block;"
[(update)]="updateFromInput"
[callbackFunction]="chartCallback">
</highcharts-chart>
Does anyone know what is wrong with this code. How can I fix it so that the gauge actually shows up?
If anyone can recommend any other package I can use to show real time data on a gauge I would appreciate it. This package should be easy to use, or at least have more resources than Highcharts where one can find tutorials an so on.
Thanks in advance!
There are a few glitches:
The highcharts-more module is missing. Import it at the begging
import HC_more from "highcharts/highcharts-more";
HC_more(Highcharts);
Your demo was not working simply because there was nothing to show.
All you have to do to fix this is to set the data in the series object.
Remember to always add the series type for each series.
series: [
{
type: "gauge",
data: [80]
}
]
Also, I highly recommend Highhcarts official documentation where you might find more examples and descriptions.
API:
https://api.highcharts.com/highcharts/series.gauge
https://github.com/highcharts/highcharts-angular
Demo:
https://stackblitz.com/edit/highcharts-angular-gauge

How do we put labels on pie chart arcs - chart.js/vue-chart.js

I am using VueChart js/ chart js to create a pie chart in my vue project, I would like to show % of data inside the each arcs, how do we do it?
My code in Vue:
fillData() {
this.datacollection = {
labels: ['T', 'W', 'R', 'B'],
datasets: [
{
backgroundColor: [
'rgb(51,122,183)',
'rgb(226,142,65)',
'rgb(0,169,157)',
'rgb(217,83,79)',
],
data: [
this.tw.length,
this.w.length,
this.r.length,
this.b.length,
],
hoverBackgroundColor: ['#0275d8', '#f0ad4e', '#5cb85c', '#d9534f'],
},
],
};
this.options = {
responsive: true,
maintainAspectRatio: false,
devicePixelRatio: 2,
tooltips: {
enabled: true,
},
title: {
display: true,
text: 'Arcs state %',
position: 'bottom',
fontSize: 20,
},
};
},
UPDATE I tried the plugin recommended by #zb22 and this but it's not working. I did install the plugin through npm
this.options = {
plugins: {
labels: {
render: 'percentage',
fontColor: ['white', 'white', 'white'],
precision: 2,
},
},
};
I have something like below, and it shows data only when I hove over each arc
My aim is to display my chart as below:
You can use a plugin to achieve this:
https://github.com/emn178/chartjs-plugin-labels
It's well known for this purpose.
This is a demo
Chart js supported plugins page does have a solution for it, it is this plugin chartjs-plugin-datalabels . Make sure you import the module in main.js as like
import labels from 'chartjs-plugin-datalabels';
and then
Vue.use(labels)
and update your Vue page :
this.options = {
plugins: {
labels: [
{
render: 'value',
}
],
},
};
Update: A easier to use module/plugin as mentioned by #zb22 is plugin chartjs-plugin-labels
If you are using vue just import it in your Vue component like
import 'chartjs-plugin-labels';
and use it like
this.options = {
plugins: {
labels: [
{
render: 'percentage',
fontColor: ['green', 'white', 'red'],
precision: 2,
}
],
},
};

Incorrect visualization of c3.js graph

I am trying to draw a very basic line chart using c3.js in react. But the the chart output appears with dark areas around the lines, which I assume is not a feature of the graph, because I used another graph library and the dark areas persisted. Anyone knows what the source of error can be?
Here is a picture of how the chart looks like:
Here is the code:
import React from "react";
import * as c3 from 'c3'
class Hello extends React.Component {
drawGraph = () =>
{
var chart = c3.generate({
bindto: this.refs.chart,
data: {
xs: {
'data1': 'x1',
'data2': 'x2',
},
columns: [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190]
]
}
});
}
render() {
return (
<div>
<br/>
<div id='chart' ref={'chart'} style={{width: '100%', height: '100%'}}><button onClick={this.drawGraph}>draw</button></div>
</div>
);
}
}
export default Hello;
If the package was installed using npm (i.e. npm install c3 or yarn add c3), it's necessary import the styles from .css files: Inside the main component, add the line
import "c3/c3.min.css";
Apparently the problem can be solved just by adding a single line of code in the beginning:
import "../../node_modules/c3/c3.css";
If you come across here as I did from top results of google search, you will be probably surprised why both of other solutions don't work.
In Vue 3 Cli there is issue with .css file loader not working properly, but you can circumvent this if you add to your main.js file, following line:
require('c3/c3.css');// C3 chart styles
This will enable you to use c3 in rest of your project, with importing c3 in components like so:
<template>
<div id="testChart"></div>
</template>
<script>
var c3 = require('c3');
export default {
async mounted() {
c3.generate({
bindto: "#testChart",
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
}
};
</script>

How to wrap this behavior in a plugin?

Currently I have a request to have a Bullet Chart with two targets (min and max).
To do it I am simply using a normal Bullet Chart with a Scatter series to draw the other target. I would like to wrap this behavior inside the bullet chart, so it would have something like the following options:
series: [{
data: [{
y: 275,
target: 250,
minTarget: 100
}]
},
And then, on the wrap, I would get this minTarget and make a scatter plot automatically. How can I do it?
Here's the fiddle I have so far: http://jsfiddle.net/gwkxd02p/
I do not think that render is a good method to add another series - anyway, you can try to do it like this:
Highcharts.wrap(Highcharts.seriesTypes.bullet.prototype, 'render', function(p) {
if (!this.hasRendered) {
const scatterData = this.points
.map(({ x, y, options }) => ({
x,
y: options.minTarget !== undefined ? options.minTarget : null
}))
if (scatterData.length) {
const scatter = this.chart.addSeries({
type: 'scatter',
data: scatterData,
marker: {
symbol: 'line',
lineWidth: 3,
radius: 8,
lineColor: '#000'
}
}, false)
scatter.translate()
scatter.render()
}
}
p.call(this)
})
And data for bullet:
series: [{
data: [{
y: 275,
target: 250,
minTarget: 100
}, {
y: 100,
target: 50
}, {
y: 500,
target: 600,
minTarget: 20
}]
live example: http://jsfiddle.net/n4p0ezzw/
I think that the better place is bullet's init method but in that method the points do not exist yet - so you would have to match the x values (if it is needed) on your own.
My suggestion is - do not wrap Highcharts if you don't have to. A better (simpler, safer, cleaner, easier to debug, it does not change Highcharts internal code) practice would be to wrap the Highcharts constructor in a function and parse the options inside it and then call the chart constructor with new options, like this:
function customBullet(container, options) {
const newOptions = {} // parse options, check for minTarget, etc. and create new options
return Highcharts.chart(container, newOptions)
}

Categories

Resources