How to integrate chartjs-chart-financial with chart js - javascript

I'd like to use chartjs-chart-financial to plot a 'candlestick' chart. However, chartjs-chart-financial isn't published to npm yet. I run an npm install followed by gulp build in the directory that has the cloned repo from https://github.com/chartjs/chartjs-chart-financial. I see chartjs-chart-financial.js in the dist folder after it has built. However, I'm clueless as to how to get this to integrate with the base chart.js library, so that I can specify a type: candlestick on my Chart. I haven't been able to come across any examples where this is demonstrated..
I'm currently using react-chartjs-2 as a wrapper around chart.js since I'm working in React:
import React, { Component } from 'react';
import Chart from '../node_modules/chart.js/dist/chart';
class Financial extends Component {
constructor() {
super();
this.myRef = React.createRef();
}
componentDidMount() {
const ctx = this.myRef.current;
this.myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["A", "B", "C"],
datasets: [{
label: 'Test',
data: [12, 20, 15],
backgroundColor: 'gray'
}]
}
});
}
render() {
return (
<canvas ref={this.myRef}/>
);
}
}
export default Financial;
As you can see, I'm rendering a sample chart with type bar for now. I'd like to be able to use type 'candlestick' instead, along with its associated dataset.
I'd appreciate any help!!

Related

How to update a chart on prop change in vue-chartjs

First, I would like to emphasize that I am a completely new to Vue (and webdev in general).
I have to make a UI where I have to show some data that I fetch from an API. But I have some issues with chart.js: I can't update my chart when prop change.
Currently, I have the following setup:
Card.vue:
<script>
import DoughnutChart from './DoughnutChart.js'
export default {
name: 'Card',
components: {
DoughnutChart
},
props: ['scheda'],
created() {
console.log(this.scheda)
}
}
</script>
<template>
<DoughnutChart type="abcd" :chartData="this.scheda"/>
</template>
DoughnutChart.js:
import { defineComponent, h } from 'vue'
import { Doughnut } from 'vue-chartjs'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
ArcElement,
CategoryScale
} from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
export default defineComponent({
name: 'DoughnutChart',
components: {
Doughnut
},
props: ['type', 'chartData'],
setup(props) {
const chartData = {
labels: ['A', 'B'],
datasets: [
{
backgroundColor: ["#ff3333", "#131b2e"],
cutout: "75%",
borderWidth: 0,
data: [props.chartData.value, (100 - props.chartData.value)]
}
]
}
const chartOptions = {
plugins: {
legend: {
display: false
}
},
responsive: true,
maintainAspectRatio: false
}
return () =>
h(Doughnut, {
chartData,
chartOptions
})
}
})
this.scheda is a reactive value and when it changes the chart should update accordingly.
I have read the documentation, but I simply can't wrap my head around it.
I have also tried searching on the internet, but all examples reference the older version of the chart library.
Can someone help me with this issue? Thanks!
If you want to create a chart js and integrate with view, you can create your canvas on js outside of vue js flow, and then get the element reference inside vue and then integrate it, the big problem rendering components inside vue is that you need update your charts, it may cause unexpected behavior on canvas. Because tools like Vue are designed to refresh the html and canvas always are a single html tag with a lot of interactivity in js(not much html).
Vue-chart
You can install
vue-chart.js
It supports data updates and also you can access to the chart ref.
Updating charts: https://vue-chartjs.org/guide/#updating-charts
Acesing to ref: https://vue-chartjs.org/guide/#access-to-chart-instance

Chartjs backgroundColor for line chart does not appear in Vue app

I'm trying to render a background (gradient, but simple color also doesn't work) for a line chart using chart.js 3.6.0 in a Vue 3 app. Users can toggle between a bar chart and a line chart (for the same dataset). Interestingly it works for the bar chart:
But the line chart has no gradient:
This is the data configuration:
data: {
labels: props.labels as string[],
datasets: [
{
data: props.data as number[],
backgroundColor: getBackgroundColor(), // returns the gradient
borderColor: getBorderColor(), // returns a color
fill: true // tried all possible values for this
}
]
}
I have tried to remove everything that might cause an issue, but even the most basic configuration with hard-coded data doesn't work.
The canvas is accessed using a ref:
<template>
<canvas class="statistics-canvas" ref="canvas" width="100%" height="100%"></canvas>
</template>
<script lang="ts">
// ...
setup() {
const canvas = ref(document.createElement("canvas"));
let chart: Chart;
onMounted(() => createChart());
function createChart() {
chart = new Chart(canvas.value, {/*...*/});
}
return {
canvas
};
}
</script>
Any ideas about what might be causing this? I have also tried coping the configuration from the chartjs docs (https://www.chartjs.org/docs/latest/charts/line.html), but also no luck.
Please check the registrar file for chart js in your project. Add Filler to Chart.register()
import {
...,
Filler,
} from 'chart.js';
Chart.register(
...,
Filler,
);

Is there a max width of canvas Chart.js can draw charts within?

I recently started working with chart.js with react wrapper for a project. And when I was building this one chart which has a width of 20000px the bars stopped appearing on the screen after the 16390px length.
My chart was scrollable and I had a large dataset due to which the canvas have huge lengths. So I was confused if there is some length limit chart.js can draw its canvas upto.
Here is my code to replicate the issue with attached screenshots.
import React, { Component, createRef } from 'react'
import ChartJsComponent from "react-chartjs-2";
class ScrollableChartJsPlugin extends Component {
chartRef = createRef()
render(){ //this will simply return the chart
return <ChartJsComponent
ref={this.chartRef}
{...this.props}
/>
}
}
export default ScrollableChartJsPlugin;
import React, { Component } from 'react'
import ScrollableChart from "../../components/ScrollableChartJSPlugin";
class Observe extends Component {
getRandomLabel = () => {
let data = [];
for(let i = 0; i<1000; i++){
data.push(`Label ${i}`)
}
return data;
}
render(){
var data = {
labels: this.getRandomLabel(),
datasets: [
{
backgroundColor: 'rgba(237, 77, 77,1)',
borderColor: 'rgba(237, 77, 77,1)',
borderWidth: 1,
hoverBackgroundColor: 'rgba(237, 77, 77,0.8)',
hoverBorderColor: 'rgba(237, 77, 77,1)',
data: this.getRandomLabel().map(el => 1000) //i am taking same value for all the bars as it'll be easier to catch when bars disappears
}
]
};
var width = this.getRandomLabel().length * 50; //this will give each bar around 50px width and total width of the chart will go around 50000px
return <div style={{width: width}}>
<ScrollableChart
type={"bar"}
height={220}
width={width}
data={data}
getElementAtEvent={this.handleChartClick}
options={
{
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display:false
}
}],
yAxes: [{
gridLines: {
display:false
}
}]
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
/>
</div>
}
}
export default Observe;
screenshot produced by the result of the above code.
So, In case there is a max width limit in chart.js for drawable canvas, Can I get it work with any workaround or any fix that is applicable for this.
Thanks
Posting for anyone who will be struggling with similar issue in the future.
After a lot of research for last two days. I found out the problem was basically with the browser.
Actually there is a limit a browser can draw a canvas upto after that limit no draw command works and the chart is not drawn any further.
checkout below thread for details.
Maximum size of a <canvas> element
That was the details of the problem. And for solution, in our case we were fetching the data from an api and then was showing in the chart, so we restricted the the max data we can hold and started deleting elements previously loaded as more data is loaded.
And that worked for us.
You can also check out this thread on github regarding this issue.
https://github.com/chartjs/Chart.js/issues/6068

React and react-chartjs-2, Line chart not displaying data from API

I am trying to render a Line chart using react-chartjs-2. Right now it works fine when I pass in static props to the Line Component. But, when I fetch data from an API, set it to a variable, then pass that variable as the prop. My Line Component is not re-rendering with the new data.
I am logging the props being passed into the Line Component and I can see it first arrives as null and then I receive the good data from the API. So it looks like the Line Component is not re-rendering after receiving the props? I am probably doing this wrong. Please help.
import React from "react";
import { Line } from "react-chartjs-2";
export default class ExpenseChart extends React.Component {
constructor(props) {
super(props);
this.state = {
marketData: [100, 200, 300],
chartData: {
labels: this.props.monthNames,
datasets: [
{
backgroundColor: "rgba(142, 243, 197, 0.5)",
pointBackgroundColor: "#fff",
pointHoverBackgroundColor: '#fff',
pointStyle: "circle",
label: "Monthly Expenses",
borderColor: "#2be1d8",
borderWidth: 3,
borderJoinStyle: "round",
lineTension: 0.3,
fontColor: "#fff",
hitRadius: 5,
hoverRadius: 8,
radius: 4,
data: this.props.monthExpenses
},
],
},
};
}
render() {
console.log("why no names", this.props.monthNames)
return (
<div className="expenseChart">
<h2 className="expenseChart__name">{this.props.graphname}</h2>
<Line
data={this.state.chartData}
options={{
maintainAspectRatio: false,
responsive: true,
aspectRatio: 3,
scales: {
yAxes: [
{
ticks: {
display: false,
},
},
],
},
layout: {
padding: {
right: 10,
},
},
}}
/>
</div>
);
}
}
And then the parent component is connected to a redux store and it looks like this:
import React from "react";
import { connect } from 'react-redux';
import ExpenseChart from "../elements/ExpenseChart";
import { fetchExpenses } from '../../actions/index';
class Dashboard extends React.Component {
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
render() {
let labels = this.props.months && this.props.months;
return (
<main className="dashboard">
<ExpenseChart
monthNames={labels}
monthExpenses={["123", "123", "12312", "12341", "231231", "1231", "1231"]}
// I am receiving monthExpenses props into the ExpenseChart component
// but not monthNames
/>
</main>
);
}
}
const mapStateToProps = state => ({
auth: state.app.auth,
months: state.app.months,
});
export default connect(mapStateToProps)(Dashboard);
I've done something similar before, fetching data from an API and passing it as props to the Line Component. But only difference is I am using redux here. And obviously, this time the Line Component is not receiving the good data.
The issue might be on this componentDidMount code.
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
As per docs on dispatch
action (Object†): A plain object describing the change that makes
sense for your application. Actions are the only way to get data into
the store, so any data, whether from the UI events, network callbacks,
or other sources such as WebSockets needs to eventually be dispatched
as actions. Actions must have a type field that indicates the type of
action being performed. Types can be defined as constants and imported
from another module. It's better to use strings for type than Symbols
because strings are serializable. Other than type, the structure of an
action object is really up to you. If you're interested, check out
Flux Standard Action for recommendations on how actions could be
constructed.
Here fetchExpenses might be returning a promise and in that case you might need
fetchExpenses().then(apiRes => dipatch({type: "ACTION_TYPE": payload: apiRes}))
Another approach can be to use redux-thunk
Ok I solved this just by checking if the data I was receiving was not null before passing it as props. Which is what I thought this line would do let labels = this.props.months && this.props.months;
<main className="dashboard">
{ this.props.months != null ? <ExpenseChart monthNames={labels}/> : ''; }
</main>

VueJs/ChartJs - single file component computed property only renders when I click the component in Vue Dev Tools

I have a single file component that uses Chart.Js to render a simple visualization for some hard coded data. I'm calling the Chart.Js library through a CDN in the head section of my index.html.
I'm using the official Webpack template.
For some reason, the chart won't render unless I click on the component inside the Vue Dev Tools extension.
I've tried changing it from computed to created/mounted and that hasn't worked.
Here's my code. Any help getting this to render properly would be much appreciated.
<template lang="html">
<div>
<div class="row">
<div class="col-sm-12 col-md-4">
<canvas id="carbChart"></canvas>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
calories: 3000,
childSex: 'male',
childAge: 'eighteen'
}
},
computed: {
nutrientCharts: function() {
let calories = this.calories;
let carbCtx = document.getElementById('carbChart').getContext('2d');
let carbChart = new Chart(carbCtx, {
type: 'doughnut',
data: {
labels: ['Low', 'Good', 'Too Much'],
datasets: [{
label: 'carbs',
data: [calories * .45, calories * .65, calories * 1],
backgroundColor: ['orange', 'blue', 'red']
}]
}
});
}
}
}
</script>
You have defined the method in a computed property but never used it.
Assuming you want to just get this running, load the chart on mounted:
mounted() {
this.nutrientCharts();
},
methods: {
nutrientCharts: function () {
// your code here
}
}

Categories