Can't reuse a template in Vue.js - javascript

Trying to reuse a custom template from my Graph.vue file, but this attempt fails(without any errors in the console). I only get one chart rendered(the red one). Any ideas how to fix this code?
My current code looks like this:
main.js
import Vue from 'vue';
import Graph from './components/Graph.vue';
new Vue({
el: 'graph',
components: { Graph }
});
Graph.vue
<template>
<canvas height="400" width="600"></canvas>
</template>
<script>
import Chart from 'chart.js';
export default {
props: ['labels', 'values', 'color'],
props: {
labels: {},
values: {},
color: {
default: 'rgba(220,220,220,0.2)'
}
},
mounted(){
var data = {
labels: this.labels,
datasets: [
{
label: "My First dataset",
fill: true,
lineTension: 0.1,
backgroundColor: this.color,
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: this.values,
spanGaps: false
},
]
};
new Chart(this.$el, {type: 'line', data: data});
}
}
</script>
example.html
<div style="width:600px" class="container">
<graph :labels="['January', 'February', 'March']"
:values="[10, 42, 4]"
color="red"
></graph>
</div>
<div style="width:600px" class="container">
<graph :labels="['May', 'June', 'July']"
:values="[100, 420, 99]"
color="blue"
></graph>
</div>
<script src="{{asset('/js/main.js')}}"></script>
The intended result should be two bars - red and blue one.

I think your mountpoint is wrong. el: 'graph' behavior is probably not predictable in this context (will it target the first graph element?).
Use something like that instead:
JS:
new Vue({
el: '#graphContainer',
components: { Graph }
});
HTML:
<div id="graphContainer">
<div style="width:600px" class="container>
<graph :labels="['January', 'February', 'March']"
:values="[10, 42, 4]"
color="red"></graph>
</div>
<div style="width:600px" class="container">
<graph :labels="['May', 'June', 'July']"
:values="[100, 420, 99]"
color="blue"></graph>
</div>
</div>

I like #Cobaltway answer better, but this also solves the problem.
JS:
import Vue from 'vue';
import Graph from './components/Graph.vue';
const graphs = document.querySelectorAll('graph');
for (let i = 0; i < graphs.length; ++i) {
new Vue({
el: graphs[i],
components: { Graph }
});
}

Related

Conflict lifecycle Graph.js and firebase data

I'm stuck to display a list of graph from data of a realtime database firebase.
At the moment I can display a list of graph, however I can't get the data of the list : "listData" .
When I change the lifecycle "ngAfterViewInit" by "ngAfterViewChecked", it works for displaying the Graph and the data of listData, however I want to do this cycle once.
If the lifecycle is ngAfterViewInit I can't display the graph
my script
#ViewChildren('pr_chart') chartElementRefs: QueryList<ElementRef>;
constructor(
public afDB: AngularFireDatabase,
public afSG: AngularFireStorage,
public afAuth: AngularFireAuth,
){ }
listData = []
chartData1 = [];
charts= [];
colorCurve = null;
colorCurveFull = null;
ngAfterViewInit() {
this.chartData1 = [1,2,3,4,5,6];
this.afDB.list('db').snapshotChanges(['child_added']).subscribe(async mybets => {
mybets.forEach(mybet => {
this.listData.push({
data : mybet.payload.exportVal().bankroll)
});
var data = Object.values(mybet.payload.exportVal().bankroll);
({result: this.colorCurve, result_full: this.colorCurveFull} = this.giveColor(Object.values(data)));
});
this.charts = this.chartElementRefs.map((chartElementRef, index) => {
return new Chart(chartElementRef.nativeElement, {
type: 'line',
data: {
labels: Object.keys(this.listData[index]["data"]),
datasets: [
{
label: "Test",
fill: true,
borderCapStyle: 'butt',
borderDash: [],
backgroundColor: this.colorCurve,
borderColor: this.colorCurveFull,
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: Object.values(this.listData[index]["data"]),
spanGaps: false,
}
]
},
options: {
scales: {
yAxes: {
title: {
display: true,
text: "Bankroll (100€/match)",
font: {
size: 10
}
},
ticks: {
precision: 0
}
},
xAxes: {
title: {
display: true,
text: "Number value bets",
font: {
size: 10
}
}
}
},
plugins: {
legend: {
display: false,
}
}
}
});
});
// this.chartData1 = Array.from(Array(this.listData.length).keys())
// console.log("test ", this.chartData1 )
});
}
}
my html script :
<ion-card *ngFor="let data of listData" >
<ion-card-content>
<canvas #pr_chart></canvas> <!--I can't display the graph-->
</ion-card-content>
</ion-card>
<ion-card *ngFor="let data of chartData1" >
<ion-card-content>
{{listData[0].country}} <!--I can't display list data-->
<canvas #pr_chart></canvas> <!--I can display the graph-->
</ion-card-content>
</ion-card>
I've tried to changed by other lifecycle and nothing works correctly... If someone can help me !

Issue While Passing Dynamic Datas in React Chart Js 2

I have successfully passed dynamic datas to React Chart JS 2 but i am having problem displaying it.
Please find the attached screenshot of the chart.
I am trying to make a line chart for all the expenses vs month. As you can see there are two arrays that is visible in the console of the screenshot. One is of Amount spent and corresponding month it was spent can be seen in the array below it. Eg: 529 was spent on May and 100 was spent on April.
Here is my Chart.js
import React from 'react';
import {connect} from 'react-redux';
import {Line} from 'react-chartjs-2';
import moment from 'moment';
const Chart = (props) => {
console.log(props.expenses);
const amount = props.expenses.map((expense) => {
// console.log(expense.amount);
// console.log(moment(expense.createdAt).format('MMMM'));
return expense.amount;
});
console.log(amount);
const createdAt = props.expenses.map((expense) => {
const arr_createdAt = expense.createdAt;
return moment(arr_createdAt).format('MMMM');
});
console.log(createdAt);
const data = {
labels: **createdAt**,
datasets: [
{
label: 'My First dataset',
fill: false,
lineTension: 0.1,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: **amount**
}
]
};
return (
<div>
<div className = "page-header">
<div className = "content-container">
<h1 className = "page-header__title">CHART</h1>
</div>
</div>
<div className = "content-container">
<h2>Line Example</h2>
<Line data={data} />
</div>
</div>
)};
const mapStateToProps = (state) => {
return {
expenses : state.expenses
};
}
export default connect(mapStateToProps)(Chart);
What i want to do is bucket all the expenses that was spent on May and dispaly total expense sum in May Line and do same for other months as well.
Any help is much appreciated.
Thank You
Try this:
`let reducedValue = props.expenses.reduce((acc, item) => {
let index = acc.findIndex(accItem => moment(accItem.createdAt).format('MMM') === moment(item.createdAt).format('MMM'));
if(index < 0){
acc.push({...item});
} else {
acc[index].amount += item.amount;
}
return acc;
}, []);
let amount = reducedValue.map(item => item.amount);
let createdAt = reducedValue.map(item => moment(item.createdAt).format('MMM'));
`

Dynamic information in chart.js radar chart

I created a radar chart in chart.js. How do I update the chart with numbers the user specifies with a drop down menu? I created a variable for each input as follows: "spaceScore", "styleScore", "scheduleScore", "supplementScore".
$(document).ready(function(){
"use strict";
new Chart(document.getElementById("radarChart"), {
type: 'radar',
data: {
labels: ["Space", "Style", "Schedule", "Supplement"],
datasets: [
{
label: "Cognizant Baseline",
fill: false,
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(179,181,198,1)",
data: [1,3,1,2]
}, {
label: "Assessment",
fill: true,
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(255,99,132,1)",
data: ['spaceScore','styleScore','scheduleScore','supplementScore']
}, {
label: "Learner Centricity",
fill: true,
backgroundColor: "rgba(114, 205, 244,0.2)",
borderColor: "rgba(114, 205, 244,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(114, 205, 244,1)",
data: [2,2,2,1]
}
]
},
options: {
title: {
display: false,
},
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
function getData(){
var radarChart = document.getElementById("radarChart");
var spaceScore = document.getElementById('spaceScore').value();
var styleScore = document.getElementById('styleScore').value;
var scheduleScore = document.getElementById('scheduleScore').value;
var supplementScore = document.getElementById('supplementScore').value;
radarChart.update;
}
});
I added 4 number inputs as an interface to update values. I gave them values ranging from 0 to 3, adapt to your needs. I also added an update button, so that the update happens only when you click it.
If you want specifically drop-down inputs, just replace the number inputs with traditional <select> tags, with <options> matching possible values.
To perform the actual update on the chart you need to first overwrite the old data from the dataset, then call a rerendering of the char-canvas with radarChart.update(). Follow the inline code comments to get an idea of whats happening in code.
$(document).ready(function() {
"use strict";
// hold a radarChart reference for future updates
var radarChart = new Chart(document.getElementById("radarChart"), {
type: 'radar',
data: {
labels: ["Space", "Style", "Schedule", "Supplement"],
datasets: [{
label: "Cognizant Baseline",
fill: false,
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(179,181,198,1)",
data: [1, 3, 1, 2]
}, {
label: "Assessment",
fill: true,
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(255,99,132,1)",
data: ['spaceScore', 'styleScore', 'scheduleScore', 'supplementScore']
}, {
label: "Learner Centricity",
fill: true,
backgroundColor: "rgba(114, 205, 244,0.2)",
borderColor: "rgba(114, 205, 244,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(114, 205, 244,1)",
data: [2, 2, 2, 1]
}]
},
options: {
title: {
display: false,
},
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
// click handler of the update button
$('#update').on('click', function() {
getData();
});
function getData() {
// get new user-selected values
var spaceScore = document.getElementById('spaceScore').value;
var styleScore = document.getElementById('styleScore').value;
var scheduleScore = document.getElementById('scheduleScore').value;
var supplementScore = document.getElementById('supplementScore').value;
// update chart dataset with new values
radarChart.data.datasets[0].data[0] = spaceScore;
radarChart.data.datasets[0].data[1] = styleScore;
radarChart.data.datasets[0].data[2] = scheduleScore;
radarChart.data.datasets[0].data[3] = supplementScore;
// redraw chart
radarChart.update();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inputs">
<input id="spaceScore" type="number" min="0" max="3" value="1" />
<input id="styleScore" type="number" min="0" max="3" value="3" />
<input id="scheduleScore" type="number" min="0" max="3" value="1" />
<input id="supplementScore" type="number" min="0" max="3" value="2" />
<button id="update" type="button">Update</button>
</div>
<canvas id="radarChart" />

Angular2 ng2-chart customizations?

I have started to use angular2 ng2-chart. I have few questions regarding the below image which I created using angular2 ng2-chart but still want to do more customization:
Questions:
1) How can I draw a dotted-line between two points when there are no values like in above image Nov-7 has value 0 (zero)?
2) How can I make a shadow effect, opacity or a combination of more than one colors?
3) How can I get the value of y-axis when I hover on any of the defined point and also if I want to change the y-axis grid color on mouse hover. What is the best way to do it using ng2-chart hover function?
Current sample code and config file:
index.html
<div class="container">
<div class="row">
<div class="overview-page">
<div class="overview-page-title">
<h2>Overview</h2>
</div>
<div class="chart-view">
<canvas baseChart
class="chart"
[datasets]="charts.datasets"
[labels]="charts.labels"
[colors]="charts.chartColors"
[options]="charts.options"
[legend]="false"
[chartType]="charts.type"
(chartHover)="chartHovered($event)">
</canvas>
</div>
</div>
</div>
</div>
index.component.ts
import {Component, Output, EventEmitter, OnInit} from '#angular/core';
import {Router} from '#angular/router';
import {Config} from '../../../config/config';
#Component({
templateUrl: 'index.html',
styleUrls: ['../../../../common/stylesheets/pages/index.scss']
})
export class IndexComponent implements OnInit {
protected charts: any;
ngOnInit() {
this.charts = (<any>Config.get('test')).charts;
console.log(this.charts);
}
chartHovered(e:any):void {
console.log(e);
}
}
Config.ts:
import * as Immutable from 'immutable';
export const Config = Immutable.Map({
test: {
charts: {
datasets: [{
data: [40, 48.2, 0, 52.6, 51.1, 57.6, 74.8]
}],
labels: ['Nov 5', 'Nov 6', 'Nov 7', 'Nov 8', 'Nov 9', 'Nov 10', 'Nov 11'],
type: 'line',
options: {
scales: {
xAxes: [{
gridLines: {
color: 'rgba(171,171,171,1)',
lineWidth: 1
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
max: 100,
min: 0,
stepSize: 25
},
gridLines: {
color: 'rgba(171,171,171,1)',
lineWidth: 0.5
}
}]
},
responsive: true
},
chartColors: [{
backgroundColor: 'rgba(25,10,24,0.2)',
borderColor: 'rgba(225,10,24,0.2)',
pointBackgroundColor: 'rgba(225,10,24,0.2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(225,10,24,0.2)'
}]
}
}
});
I couldn't find the best answer to your first question. However you can define multiple datasets with no intersection and use different colours (see the point 2) for that one.
http://valor-software.com/ng2-charts/
For the second one when you define colours, as you are already doing it in your code:
chartColors: [{
backgroundColor: 'rgba(25,10,24,0.2)',
borderColor: 'rgba(225,10,24,0.2)',
pointBackgroundColor: 'rgba(225,10,24,0.2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(225,10,24,0.2)'
}
The last number in rgba is the opacity. For having different colours the option is to define multiple datasets, otherwise it randomises the colours and you won't get mixed ones. A plunker here:
http://plnkr.co/edit/9PckMZiDYZjRz1PA0Suq
For the last question regarding getting the value of x-axis, look at the event which is logged to console on bounded events.

Is there a way to use rxjs with ng2-charts?

I cant find a way to implement a live charts with ng2-charts.
I get an error when I do :
<div *ngIf="(lineChartData$ | async)!=null">
....
<canvas baseChart width="100" height="200"
[datasets]="lineChartData$ | async" <<-ERROR: "Cannot read property 'data' of undefined"
....
</canvas>
</div>
I think that even if I would make it work some how, it would be the worst way to do it.
Please recommend on any other liberies that has a build-in live charts if there is no solution to this error.
EDIT:
app.component.html:
<div *ngIf="(lineChartData$ | async)!=null">
<div class="row">
<div class="col-md-6">
<div style="display: block;">
<canvas baseChart width="100" height="200"
[datasets]="lineChartData$ | async" <<<-- ERROR
[labels]="lineChartLabels"
[options]="lineChartOptions"
[colors]="lineChartColors"
[legend]="lineChartLegend"
[chartType]="lineChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
</div>
<div class="col-md-6" style="margin-bottom: 10px">
<table class="table table-responsive table-condensed">
<tr>
<th *ngFor="let label of lineChartLabels"></th>
</tr>
<tr *ngFor="let d of lineChartData">
<td *ngFor="let label of lineChartLabels; let j=index"></td>
</tr>
</table>
</div>
</div>
</div>
app.component.ts:
import {Component, OnInit} from '#angular/core';
import {Observable} from "rxjs";
import {Store} from "#ngrx/store";
import {AppState} from "../../redux/design/app-state";
import {AngularFire, AuthProviders, FirebaseObjectObservable} from "angularfire2";
import 'rxjs/add/operator/withLatestFrom';
import {AuthActions} from "../../redux/actions/auth.actions";
import {UserService} from "../../services/user.service";
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit
{
private lineChartData$:Observable<Array<any>>;
constructor(private authActions: AuthActions,
private af: AngularFire,
private userService:UserService,
private store:Store<AppState>){}
public ngOnInit(): void {
this.lineChartData$=Observable.interval(500)
.map(index=>[{data: [65, 59, index, 81, 56, 55, 40], label: 'Series A'},
{data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B'},
{data: [18, 48, 77, 9, 100, 27, 40], label: 'Series C'}
]);
}
// lineChart
public lineChartLabels:Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
public lineChartOptions:any = {
animation: false,
responsive: true,
maintainAspectRatio: false
};
public lineChartColors:Array<any> = [
{ // grey
backgroundColor: 'rgba(148,159,177,0.2)',
borderColor: 'rgba(148,159,177,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)'
},
{ // dark grey
backgroundColor: 'rgba(77,83,96,0.2)',
borderColor: 'rgba(77,83,96,1)',
pointBackgroundColor: 'rgba(77,83,96,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(77,83,96,1)'
},
{ // grey
backgroundColor: 'rgba(148,159,177,0.2)',
borderColor: 'rgba(148,159,177,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)'
}
];
public lineChartLegend:boolean = true;
public lineChartType:string = 'line';
// events
public chartClicked(e:any):void {
console.log(e);
}
public chartHovered(e:any):void {
console.log(e);
}
}
I don't know much about ng2-charts but the error suggests the problem is somewhere else.
The doc on ngOnInit says:
Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties.
So this lifecycle event is called after the view is initialized. Your lineChartData$ is defined as:
private lineChartData$:Observable<Array<any>>;
... and it's not initialized until ngOnInit() call. So the view tries to bind lineChartData$ which is still undefined at that time. Thus the error message thrown probably from ng2-charts internals.

Categories