I need to change the values and re-initiate the component with props Data.
i tried with $emit unfortunately doesn't work my code.
chart.vue
<template>
<div class="col-12">
<div class="card">
<div class="card-header header-elements">
<div>
<h5 class="card-title mb-0">Statistics</h5>
</div>
<div class="card-header-elements ms-auto py-0">
<select name="status" class="form-select form-select-sm" v-model="chartType" #click="$emit('someEvent')">
<option value="daily" data-label="Days">Last 7 Days</option>
<option value="weekly" data-label="Weeks">Weekly</option>
<option value="monthly" data-label="Months">Monthly</option>
</select>
</div>
</div>
<div class="card-body">
<line-chart v-bind:chartData="chartData" v-bind:chartOptions="chartOptions" v-if="showLineGraph" #some-event="chartData"></line-chart>
</div>
</div>
</div>
</template>
<script>
export default {
props: {},
mounted() {
},
created(){
this.params.params = {
chart_type: "daily",
};
this.chartOptions.scales.xAxes[0].scaleLabel.display = "DAYS";
this.chartOptions.scales.xAxes[0].scaleLabel.labelString = "DAYS";
this.loadGraph();
},
data() {
return {
chartType:'daily',
showLineGraph:false,
params: {
params: {}
},
datasetSample: {
data: [],
label: "",
borderColor: "#ff5b5c",
tension: 0.5,
pointStyle: "circle",
backgroundColor: "#ff5b5c",
fill: false,
pointRadius: 1,
pointHoverRadius: 5,
pointHoverBorderWidth: 5,
pointBorderColor: "transparent",
pointHoverBorderColor: "#fff",
pointHoverBackgroundColor: "#ff5b5c",
height: 500
},
chartData: {
labels: [],
datasets: []
},
chartOptions: {
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
scaleLabel: {
display: "",
labelString: ""
},
gridLines: {
display: true,
},
}],
yAxes: [{
beginAtZero: true,
scaleLabel: {
display: "Amount In INR",
labelString: "Amount In INR"
},
gridLines: {
display: true,
},
ticks: {
maxTicksLimit: 10,
beginAtZero: false,
callback: function (value, index, values) {
return value.toLocaleString();
}
}
}]
},
legend: {
position: 'top',
align: 'start',
labels: {
usePointStyle: true,
padding: 15,
boxWidth: 6,
boxHeight: 6,
}
},
plugins: {
tooltip: {
// Updated default tooltip UI
backgroundColor: "#fff",
titleColor: "#000",
bodyColor: "#000",
borderWidth: 1,
borderColor: "#0560e8"
}
}
}
};
},
methods: {
loadGraph: function () {
this.chartData.datasets=[];
this.chartData.labels = [];
axios.get(window.location.href + "/get-chart-data", this.params)
.then(response => {
console.log(response.data);
if (response.data.status == 200) {
let datasets = response.data.data.datasets;
let chart_vlaues=[];
for (var key in datasets) {
if (datasets.hasOwnProperty(key)){
let temp_dataset = Object.assign({}, this.datasetSample);
temp_dataset.data = datasets[key].values;
temp_dataset.label = key;
temp_dataset.borderColor = datasets[key].colour;
temp_dataset.backgroundColor = datasets[key].colour;
temp_dataset.pointHoverBackgroundColor = datasets[key].colour;
chart_vlaues.push(temp_dataset);
}
}
this.chartData.datasets=chart_vlaues;
this.chartData.labels = response.data.data.labels;
this.showLineGraph=true;
}else {
this.chartData.datasets = [];
this.chartData.labels = [];
this.showLineGraph = true;
}
})
.catch(err => {
console.log(err);
console.log("Chart could not loaded.");
})
.then(() => {
});
},
}
}
</script>
LineChart.Vue
<script>
import { defineComponent } from 'vue'
import { Chart as ChartJS, Title, Tooltip, Legend,Line} from 'vue3-chart-v2'
export default defineComponent({
name: 'LineChart',
extends: Line,Tooltip,Legend,Title,
props: {
chartData: {
type: Object,
required: true
},
chartOptions: {
type: Object,
required: false
},
},
watch : {
someEvent: function (value) {
console.log('from watch');
}
},
mounted () {},
created(){
this.renderChart(this.chartData, this.chartOptions);
},
data(){
},
methods:{
someEvent:function(){
alert('iiiiiiiiii');
}
},
emits: {
someEvent(payload) {
console.log('some emits');
}
}
})
</script>
app.js
require('./bootstrap')
import { createApp } from 'vue'
import lineChart from './components/lineChart';
import chart from './components/chart.vue';
const app = createApp({})
app.component('chart', chart);
app.component('line-chart', lineChart);
app.mount('#app')
You use watchers wrong. They are not for watching events.
watch : {
someEvent: function (value) {
console.log('from watch');
}
},
You also did not define your custom event with emits
Please, check the Vue docs about the Component Events
The typical data flow with Vue components is
to the Component: App -> Data -> Component Props -> Watchers -> Methods
from The component: Data -> Event -> Event Handler -> App
So, if you want to re-initiate your child component, that you should update some child component's prop and then react to the change in some child component's watcher.
Related
I have this code to show bar-chart with VueJS:
Vue.component('bar-chart', {
extends: VueChartJs.Bar,
data: function () {
return {
datacollection: {
labels: ['MICROFINANZAS -SECTOR COMERCIO','MICROFINANZAS -SECTOR SERVICIOS'],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
pointBackgroundColor: 'white',
borderWidth: 1,
pointBorderColor: '#249EBF',
data: [15000, 71700]
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
gridLines: {
display: true
}
}],
xAxes: [{
ticks: {
beginAtZero: true
},
gridLines: {
display: false
}
}]
},
legend: {
display: false
},
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label: function (tooltipItems, data) {
return '$' + tooltipItems.yLabel;
}
}
},
responsive: true,
maintainAspectRatio: false,
height: 200
}
}
},
mounted() {
// this.chartData is created in the mixin
this.renderChart(this.datacollection, this.options)
}
})
Method in VueJS
var app = new Vue({
el: '#grid',
data: {
columns: ['id', 'nombre'],
objeto: "",
searchQuery: "",
dataChart: "",
dataChart1: "",
},
created: function () {
this.getDeudas();
},
methods: {
getDeudas: function () {
this.$http.get(baseURL + "/Home/ConsultarDeudasHome").then(function (response) {
this.lista = response.data.data;
console.log(this.lista);
this.objeto = JSON.parse(this.lista);
console.log(this.objeto[1].original);
this.dataChart = [this.objeto[0].original, this.objeto[0].actual];
console.log(this.dataChart);
this.dataChart1 = [this.objeto[1].original, this.objeto[1].actual];
});
},
},
This code show this bar chart:
But I need replace in my code two variables dynamic:
labels: ['MICROFINANZAS -SECTOR COMERCIO','MICROFINANZAS -SECTOR SERVICIOS'],
data: [15000, 71700]
With the information of method getDeudas()
How can to made this action?
This is the solution, I use props and watch:
Vue.use(VueTables.ClientTable);
Vue.component("bar-chart", {
extends: VueChartJs.Bar,
props: ["data", "options"],
mounted() {
this.renderLineChart();
},
computed: {
chartData: function () {
return this.data;
}
},
methods: {
renderLineChart: function () {
this.renderChart(
{
labels: ["Sector Comercio", "Sector Servicios"],
datasets: [
{
label: "Consolidado",
backgroundColor: "#f87979",
data: this.chartData
},
],
},
{ responsive: true, maintainAspectRatio: false }
);
}
},
watch: {
data: function () {
this.renderLineChart();
}
}
});
const baseURL = window.location.protocol + "//" + window.location.host;
var app = new Vue({
el: '#grid',
data: {
columns: ['id', 'nombre'],
objeto: "",
dataChart: "",
},
created: function () {
this.getDeudas();
},
methods: {
getDeudas: function () {
this.$http.get(baseURL + "/Home/ConsultarDeudasHome").then(function (response) {
this.lista = response.data.data;
this.objeto = JSON.parse(this.lista);
this.dataChart = [this.objeto[0].original, this.objeto[1].original];
});
},
},
})
This problem may seem to already exist but I also tried those and some are inactive now. My goal is to make the chart reactive whenever the page reloads. I tried to the solution from the Vue page itself i.e. add watchers and mixins but it doesn't work, as commented by others stuck like me. Mine only render if I change the width and height of the chart but everytime I refresh it, it disappears.
Dashboard.vue
<template>
<div align="center">
<LineChart :chartData="chartData" :options="options" style="width:auto;height:auto;" />
</div>
</template>
<script>
export default {
data() {
return {
chartData: {
labels: [],
datasets: [
{
data: [],
backgroundColor: "#3498db",
borderColor: "rgba(136,136,136,0.5)",
label: "",
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: "Student's Score Chart",
},
tooltips: {
mode: "index",
intersect: false,
},
hover: {
mode: "nearest",
intersect: true,
},
scales: {
xAxes: [
{
display: true,
scaleLabel: {
display: true,
labelString: "Student Names",
},
},
],
yAxes: [
{
display: true,
scaleLabel: {
display: true,
labelString: "Score Points",
},
},
],
},
},
mounted() {
this.getListData();
},
methods: {
getListData() {
axios
.get("http://localhost/MyComposer/", {
params: {
answerId: 6,
token: this.token,
},
})
.then((response) => {
console.log(response.data);
for (var k = 0; k < response.data.length; k++) {
const fullName =
response.data[k].FirstName +
" " +
response.data[k].MiddleName +
" " +
response.data[k].LastName;
this.chartData.labels.push(
fullName + " (" + response.data[k].TestName + ") "
);
this.chartData.datasets[0].data.push(response.data[k].Score);
console.log(this.chartData);
}
})
.catch(function (error) {
console.log(error);
});
},
}
}
ChartContainer.js
import { Line, mixins } from 'vue-chartjs'
export default {
extends: Line,
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
mounted () {
this.renderChart(this.chartData, this.options)
},
watch: {
chartData () {
this.renderChart(this.chartData, this.options)
}
}
}
I solved the problem. It was on the documentations all along. For you guys who didn't know, you should just add v-if to only enable the mounted method to activate when the page has loaded.
<line-chart
v-if="loaded"
:chart-data="this.chartData"
:options="this.options"
style="width:auto;height:auto;"
></line-chart>
data: {
loaded: false
}
getListData(){
this.loaded = true;
//My Axios API Request
}
In my react app, I'm getting results from pouchDB that I want to use as the data points in my series for apexCharts.
I'm getting the results and putting them in state, called maxCalories, and when logging in the console they are in this format:
So I want those 7 numbers (all with the index name of caloriesBurned to be my data in the series for the chart but I'm currently getting NaN on the graph.
Here's the full code, how can I set these to the correct format to use them in the chart data?
import React, { Component } from "react";
import Chart from "react-apexcharts";
import DB from '../../db';
import * as moment from 'moment';
class TrendsComponent extends Component {
constructor(props) {
super(props);
this.state = {
maxCalories: '',
calorieRecord: {
caloriesConsumed: '',
caloriesBurned: '',
createdAt: this.newestDate,
updatedAt: undefined
},
caloriesDB: new DB('calorie-records'),
calories: {},
calorieElements: null,
options: {
},
chart: {
toolbar: {
show:false
},
id: "basic-bar"
},
xaxis: {
categories: ['3/20', '3/21', '3/22', '3/23', '3/24', '3/25','3/26']
}
},
series: [
{
name: "Trend (tracked)",
data: {this.maxCalories}
}
]
};
}
componentDidMount(){
this.setMax();
}
setMax = () => {
this.state.caloriesDB.db.find({
selector: {
$and: [
{_id: {"$gte": null}},
{caloriesBurned: {$exists: true}},
{createdAt: {$exists: true}}
]
},
fields: ['caloriesBurned', 'createdAt'],
sort: [{'_id':'desc'}],
limit: 7
}).then(result => {
console.log('max');
console.log(result);
const newDocs = result.docs;
this.setState({
maxCalories: newDocs.map(docs => docs)
});
console.log('maxCalories');
console.log(this.state.maxCalories);
}).catch((err) =>{
console.log(err);
});
}
render() {
return (
<div className="mixed-chart">
<Chart
options={this.state.options}
series={this.state.series}
type="area"
stacked="true"
width="700"
/>
</div>
);
}
}
export default TrendsComponent;
I had the same problem in my project. And I spent a lot of time in looking for solution. So here what I get:
const FinacialResultChart = (props) => {
const options = {
chart: {
toolbar: {
show: false
},
animations: {
enabled: false
}
},
stroke: {
curve: "smooth",
dashArray: [0, 8],
width: [4, 2]
},
grid: {
borderColor: props.labelColor
},
legend: {
show: false
},
colors: [props.dangerLight, props.strokeColor],
fill: {
type: "gradient",
gradient: {
shade: "dark",
inverseColors: false,
gradientToColors: [props.primary, props.strokeColor],
shadeIntensity: 1,
type: "horizontal",
opacityFrom: 1,
opacityTo: 1,
stops: [0, 100, 100, 100]
}
},
markers: {
size: 0,
hover: {
size: 5
}
},
xaxis: {
labels: {
style: {
colors: props.strokeColor
}
},
axisTicks: {
show: false
},
categories: [
"Январь",
"Февраль",
"Март",
"Апрель",
"Май",
"Июнь",
"Июль",
"Август",
"Сентябрь",
"Октябрь",
"Ноябрь",
"Декабрь"
],
axisBorder: {
show: false
},
tickPlacement: "on"
},
yaxis: {
tickAmount: 5,
labels: {
style: {
color: props.strokeColor
}
}
},
tooltip: {
x: { show: false }
}
}
const data = [
{
name: "Итоговый результат",
data: props.userData.traidingMonth
}
]
return (
<Chart
options={options}
series={data}
type="line"
height={280}
/>
)
}
export default FinacialResultChart
So you need to change your class to const, and push all your props (api data for example) into your children chart component. In chart options you can get the chart data with props.data
I'm using apex charts for react in my reactJS progressive web app, and have had no issues with it for static data, but I"m now trying to take a returned array from my database and use the array for the graph and it's not working.
I'm logging the array returned from the database, which is in this structure:
And in my code, I'm setting this to the third series option of my chart named "Trends" but when the graph loads the line for that data is 'Nan'
What am I doing wrong here?
class TrendsComponent extends Component {
constructor(props) {
super(props);
this.state = {
maxCalories: '',
calorieRecord: {
caloriesConsumed: '',
caloriesBurned: '',
createdAt: undefined,
updatedAt: undefined
},
options: {
fill: {
colors: ['#FF756D', '#85DE77', '#FFF49C']
},
dataLabels: {
enabled: true,
textAnchor: 'middle',
distributed: false,
offsetX: 0,
offsetY: 0,
style: {
fontSize: '14px',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 'bold',
colors: ["#FF756D", "#85DE77", "#FFF49C"]
},
background: {
enabled: true,
foreColor: '#fff',
padding: 4,
borderRadius: 2,
borderWidth: 1,
borderColor: '#fff',
opacity: 0.9,
},
dropShadow: {
enabled: true,
top: 1,
left: 1,
blur: 1,
color: '#000',
opacity: 0.8
}
},
colors: ["#FF756D", "#85DE77", "#FFF49C"],
chart: {
toolbar: {
show:false
},
id: "basic-bar"
},
xaxis: {
categories: ['3/20', '3/21', '3/22', '3/23', '3/24', '3/25','3/26']
}
},
series: [
{
name: "Baseline",
data: [250,500,234,389,644,245,590]
},
{
name: "Optimal",
data: [2250,2250,2250,2250,2250,2250,2250]
},
{
//this is the line where I'm getting NaN
name: "Trend (tracked)",
data: [this.maxCalories]
}
]
};
}
...
UPDATE:
Upon component mounting, I use these functions to set MaxCalories which is the data array I'm using for the chart
getMax = () => {
this.state.caloriesDB.db.createIndex({
index: {
fields: ['_id','caloriesBurned']
}
}).then(result => {
console.log(result);
this.setMax();
}).catch((err) =>{
console.log(err);
});
}
setMax = () => {
this.state.caloriesDB.db.find({
selector: {
$and: [
{_id: {"$gte": null}},
{caloriesBurned: {$exists: true}},
]
},
fields: ['caloriesBurned'],
sort: [{'_id':'desc'}],
limit: 7
}).then(result => {
console.log('max');
console.log(result);
const newDocs = result.docs;
this.setState({
maxCalories: newDocs.map(docs => docs)
});
console.log('maxCalories');
console.log(this.state.maxCalories);
}).catch((err) =>{
console.log(err);
});
}
I need to add a date picker that contains start and end dates. When a date is selected that should pass to API to display chart. I have currently displaying Apexchart but I need date picker for my code.
Below is my chart displaying currently now I am passing selected key and I am not getting how to pass selected date to chart.
Here I need to add date picker
<template>
<div >
<select v-model="PoleSelected" #change="getPoleDetail()" >
<option :value='0'>Select Pole</option>
<option v-for='data in PoleList' :value='data.poleid'>{{ data.poleid}}
</option>
</select>
//above dorpdown is used to select the pole
<va-card >
<h3>Temperture</h3>
<AreachartTemp :_key="PoleSelected" /> //this is my
//AreachartTemp.vue anther pageand i am passing selected key to this page
</va-card>
</div>
<div >
<va-card>
<h3>Humidity</h3>
<AreachartHumd :_key="PoleSelected"/> //this is also sepearte
// page and i am passing selected key
</va-card>
</div>
</template>
<script>
export default{
data:function() {
return {
PoleSelected:'',
}
},
components: {
AreachartTemp,
AreachartHumd,
},
}
</script>
//below is my AreachartTemp.vue page
<template>
<div id="wrapper">
<div id="chart-bar" >
<apexchart type=area height=200 :options="chartOptionsArea0"
:series="series0"/>
</div>
<div id="chart-bar">
<apexchart type=area height=100 :options="chartOptionsBrush0"
:series="series0" />
</div>
</div>
</template>
<script>
import VueApexCharts from 'vue-apexcharts'
Vue.use(VueApexCharts)
Vue.component('apexchart', VueApexCharts)
import axios from 'axios'
import Vue from 'vue';
export default {
props: {
_key: {
type: String,
required: true
}
},
data() {
return {
series0: [{
data: this.generateDayWiseTimeSeries0( 185, {
min: 30,
max: 90
})
}],
chartOptionsArea0: {
chart: {
id: 'chartArea0',
foreColor: "#ccc",
toolbar: {
autoSelected: 'pan',
show: false
}
},
stroke: {
width: 3
},
dataLabels: {
enabled: false
},
fill: {
opacity: 1,
},
markers: {
size: 2,
colors: ["#000524"],
strokeColor: "#00BAEC",
strokeWidth: 3
},
xaxis: {
type: 'datetime'
}
},
chartOptionsBrush0: {
chart: {
id: 'chartBrush',
brush: {
target: 'chartArea0',
enabled: true
},
selection: {
enabled: true,
xaxis: {
}
},
},
colors: ['#546E7A'],
fill: {
type: 'gradient',
gradient: {
opacityFrom: 0.55,
opacityTo: 0
}
},
xaxis: {
type: 'datetime',
tooltip: {
enabled: false
}
},
yaxis: {
tickAmount: 2
}
}
};
},
watch: {
_key() {
this.generateDayWiseTimeSeries0();
}
},
mounted() {
//this.updateChart();
},
methods: {
generateDayWiseTimeSeries0: function () {
var me = this;
axios.get("http://34.67.88.0:3000/api/eco/temp/"+this._key)
.then(function (res) {
me.series0[0].data=res.data
/*me.$children[0].updateSeries([{
data: res.data
}]);
me.$children[1].updateSeries([{
data: res.data
}]);*/
})
return []
}
}
};
</script>