Not able to show graph on click of a button - html

Graph is not displayed on click. I have
I have two child components
Data component for showing the list of employees
Rating component for showing employee's respective rating
I have put 'graph code' inside 'ngOnInit' function in Rating component, and click button is in Data component, with help of event emitting i am trying to pass a boolean value from Data to Rating .
As you can see below in rating.component.html, if the flag value becomes true, then show graph. But even after flag becomes true, graph is not visible.
Data component
import { DataService } from './../../services/data.service';
import { Component, OnInit, Output, EventEmitter} from '#angular/core';
#Component({
selector: 'app-data',
templateUrl: './data.component.html',
styleUrls: ['./data.component.css'],
})
export class DataComponent implements OnInit {
users: { name: string; city: string }[] = [];
visible = false;
#Output() show = new EventEmitter();
constructor(private dataSerivce: DataService) {}
ngOnInit(): void {
this.users = this.dataSerivce.getEmployees();
}
toggle() {
this.visible = !this.visible;
if (this.visible) {
console.log('enter');
this.show.emit(this.visible);
} else {
this.show.emit(null);
}
}
}
Rating component
import { Rating } from './../../../../models/rating.model';
import { DataService } from 'src/app/services/data.service';
import { Component, OnInit, Input, OnChanges, SimpleChanges} from '#angular/core';
import {Chart} from '../../../../node_modules/chart.js';
#Component({
selector: 'app-rating',
templateUrl: './rating.component.html',
styleUrls: ['./rating.component.css']
})
export class RatingComponent implements OnInit ,OnChanges{
rating: Rating[] = [];
#Input() flag = false;
constructor(private dataService: DataService) { }
ngOnInit() {
console.log('init');
var myChart= new Chart('myChart', {
type: 'bar',
data: {
labels: ['Technical', 'Communication', 'Experience', 'Leadership'],
datasets: [{
label: 'skill scores',
data: [10,15, 16, 22],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
ngOnChanges(changes: SimpleChanges){
console.log('first time');
}
private getRatings($event){
this.dataService.getRating().subscribe(res =>{
this.rating.push(res);
});
}
}
Rating html code
<div style="height:40%;width:40%;" class="center" *ngIf ="flag" >
<canvas
class="chart chart-bar"
chart-data="dataChart" id = "myChart"></canvas>
</div>

While the chart.js options might be correct, the current code in RatingComponent is not referencing the chart.js options to any particular DOM Element. This could be one of the reasons why the chart is not getting rendered.
ChartJS expects a reference to a DOM Element which it shall use to render the chart.
For example:
HTML Template:
<div #barchart class="barChart"><d/iv>
RatingsComponent :
import { Component, OnInit, ViewChild } from '#angular/core';
import { Chart } from 'chart.js';
#Component({
...
})
export class RatingComponent implements OnInit {
#ViewChild('barchart') private chartRef;
chart: any;
ngOnInit() {
// provide reference of the html component to the the Chart Instance.
this.chart = new Chart(this.chartRef.nativeElement, {
// insert chart options here
});
}
}
Alternatively
After looking at your update, I think the part that is causing issue is that you are not passing the required data to the canvas component.
According to the documentation of ChartJS.
HTML Code:
<div>
<div style="display: block">
<canvas baseChart
[datasets]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[legend]="barChartLegend"
[chartType]="barChartType">
</canvas>
</div>
</div>
Component
import { Component, OnInit } from '#angular/core';#Component({
selector: 'app-my-bar-chart',
templateUrl: './my-bar-chart.component.html',
styleUrls: ['./my-bar-chart.component.css']
})
export class MyBarChartComponent implements OnInit { constructor() { }
public barChartOptions = {
scaleShowVerticalLines: false,
responsive: true
};
public barChartLabels = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
public barChartType = 'bar';
public barChartLegend = true; public barChartData = [
{data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A'},
{data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B'}
];
ngOnInit() {
}}

Related

error TS2322 in Angular with error "Type 'string' is not assignable to type '"canvas"" when using ng-particles

I am trying to have the particles.js in the home screen component. I have installed "npm install ng-particles" and "npm install tsparticles." After serving and restarting and comparing to other projects I cant seem to figure it out. Below is the error I receive, although it does still run on localhost when I ng-serve. I am pretty new to typescript and angular so I really don't understand the error.
Error: src/app/home/home.component.html:2:33 - error TS2322: Type '{ background: { color: { value: string; }; }; fpsLimit: number; interactivity: { detectsOn: string; events: { onClick: { enable: boolean; mode: string; }; onHover: { enable: boolean; mode: string; }; resize: boolean; }; modes: { ...; }; }; particles: { ...; }; detectRetina: boolean; }' is not assignable to type 'RecursivePartial<IOptions>'.
The types of 'interactivity.detectsOn' are incompatible between these types.
Type 'string' is not assignable to type '"canvas" | InteractivityDetect | "parent" | "window" | undefined'.
2 <Particles id="tsparticles" [options]="particlesOptions"></Particles>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/app/home/home.component.ts:6:16
6 templateUrl: './home.component.html',
~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component HomeComponent.
Home.component.html
<div class="particle-background">
<Particles id="tsparticles" [options]="particlesOptions"></Particles>
</div>
Home.component.ts
import { Component, OnInit } from '#angular/core';
import { NgParticlesModule } from 'ng-particles';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
particlesOptions = {
background: {
color: {
value: "white"
}
},
fpsLimit: 60,
interactivity: {
detectsOn: "canvas",
events: {
onClick: {
enable: true,
mode: "push"
},
onHover: {
enable: true,
mode: "repulse"
},
resize: true
},
modes: {
bubble: {
distance: 400,
duration: 2,
opacity: 0.8,
size: 30,
speed: 1
},
push: {
quantity: 4
},
repulse: {
distance: 100,
duration: 0.4
}
}
},
particles: {
color: {
value: "#a9a9a9"
},
links: {
color: "#a9a9a9",
distance: 200,
enable: true,
opacity: 0.7,
width: 1.5
},
collisions: {
enable: true
},
move: {
direction: "none",
enable: true,
outMode: "bounce",
random: false,
speed: 2,
straight: false
},
number: {
density: {
enable: true,
value_area: 800
},
value: 80
},
opacity: {
value: 1
},
shape: {
type: "diamond"
},
size: {
random: true,
value: 3
}
},
detectRetina: true
};
}
App.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ResumeComponent } from './resume/resume.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';
import { ProjectsComponent } from './projects/projects.component';
import { HomeComponent } from './home/home.component';
import { NgParticlesModule } from 'ng-particles';
#NgModule({
declarations: [
AppComponent,
ResumeComponent,
AboutComponent,
ContactComponent,
ProjectsComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
NgParticlesModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
I finally figured out what was the problem.
There's a property that is not part of the Options object of tsparticles
You can see it here
/* omitted for brevity */
modes: {
bubble: {
distance: 400,
duration: 2,
opacity: 0.8,
size: 30,
speed: 1 // this is the property to remove
},
/* omitted for brevity */
But you can type the options variable of the Home component using the ISourceOptions type from tsparticles to avoid any other issue.
import { ISourceOptions } from 'tsparticles';
/* omitted for brevity */
options: ISourceOptions = {
Like this.
After all these changes everything builds fine, hope everything is good after that.

Can't bind to 'configuration' since it isn't a known property of 'ng-material-multilevel-menu'

I am using ng-material-multilevel-menu plugin to create multilevel dropdown. I am following this article, but getting below runtime error
Can't bind to 'configuration'
since it isn't a known property of 'ng-material-multilevel-menu'.
1. If 'configuration' is an Angular directive, then add 'CommonModule' to the '#NgModule.imports' of this component.
2. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component.
Can't bind to 'items' since it isn't a known property of
'ng-material-multilevel-menu'.
1. If 'items' is an Angular directive, then add 'CommonModule' to the '#NgModule.imports' of this component.
2. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component.
'ng-material-multilevel-menu' is not a known element:
1. If 'ng-material-multilevel-menu' is an Angular component, then verify that it is part of this module.
2. If 'ng-material-multilevel-menu' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component
to suppress this message.
This is my code in .html file
<div>
<ng-material-multilevel-menu [configuration]='config' [items]='appitems' (selectedItem)="selectedItem($event)">
</ng-material-multilevel-menu>
</div>
This is my code in .ts file
import { Component, OnInit, NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { NgMaterialMultilevelMenuModule } from 'ng-material-multilevel-menu';
import { AppComponent } from '../app.component';
#Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css']
})
#NgModule({
declarations: [
],
imports: [
BrowserModule,
NgMaterialMultilevelMenuModule // Import here
],
providers: [],
bootstrap: [AppComponent]
})
export class ProductsComponent implements OnInit {
constructor(private employeeService: ProductService) {
}
ngOnInit() {
var appitems = [
{
label: 'Item 1 (with Font awesome icon)',
faIcon: 'fab fa-500px',
items: [
{
label: 'Item 1.1',
link: '/item-1-1',
faIcon: 'fab fa-accusoft'
},
{
label: 'Item 1.2',
faIcon: 'fab fa-accessible-icon',
items: [
{
label: 'Item 1.2.1',
link: '/item-1-2-1',
faIcon: 'fas fa-allergies'
},
{
label: 'Item 1.2.2',
faIcon: 'fas fa-ambulance',
items: [
{
label: 'Item 1.2.2.1',
link: 'item-1-2-2-1',
faIcon: 'fas fa-anchor'
}
]
}
]
}
]
},
];
});
}
How can I solve this issue?
Remove #NgModule section from this component file. Add NgMaterialMultilevelMenuModule in imports section of your app.module.ts file.
And declare appitems as global variable above the constructor like below:
export class ProductsComponent implements OnInit {
appitems: any = [];
constructor(private employeeService: ProductService) {
}
ngOnInit() {
this.appitems = [
{
label: 'Item 1 (with Font awesome icon)',
faIcon: 'fab fa-500px',
items: [
{
label: 'Item 1.1',
link: '/item-1-1',
faIcon: 'fab fa-accusoft'
},
{
label: 'Item 1.2',
faIcon: 'fab fa-accessible-icon',
items: [
{
label: 'Item 1.2.1',
link: '/item-1-2-1',
faIcon: 'fas fa-allergies'
},
{
label: 'Item 1.2.2',
faIcon: 'fas fa-ambulance',
items: [
{
label: 'Item 1.2.2.1',
link: 'item-1-2-2-1',
faIcon: 'fas fa-anchor'
}
]
}
]
}
]
},
];
});
}
First: Do not use var, just use it like this appitems=[...]
Second: You did not declare the config variable in your controller.
Third: You need to add the NgMaterialMultilevelMenuModule in the AppModule class not in the component you created.
Just define config in your ProductsComponent :
config = {
paddingAtStart: true,
interfaceWithRoute: true,
classname: 'my-custom-class',
listBackgroundColor: `rgb(208, 241, 239)`,
fontColor: `rgb(8, 54, 71)`,
backgroundColor: `rgb(208, 241, 239)`,
selectedListFontColor: `red`,
highlightOnSelect: true,
collapseOnSelect: true,
rtlLayout: false
};

How to use json data in chart.js in an ionic app

I would like to implement chart.js, I followed the example HERE, it worked well with a sample array data, but now I want to put live data fetch in json format from my server, I could not get a head way.
this is my html page
<ion-header>
<ion-navbar>
<ion-title>results</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-card >
<ion-card-header>
Bar Chart
</ion-card-header>
<ion-card-content>
<canvas width="800" height="800" #barCanvas></canvas>
</ion-card-content>
</ion-card>
</ion-content>
and my .ts page
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Chart } from 'chart.js';
import { LoadingController, AlertController } from 'ionic-angular';
import {Http, Headers, RequestOptions} from "#angular/http";
import 'rxjs/add/operator/map';
#IonicPage()
#Component({
selector: 'page-results',
templateUrl: 'results.html',
})
export class ResultsPage {
#ViewChild('barCanvas') barCanvas;
barChart: any;
selectedOption:any;
items:any;
val : any=[];
val2 : any=[];
constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, public loading: LoadingController,
public alertCtrl: AlertController) {
}
ionViewDidLoad() {
this.selectedOption = this.navParams.get('options');
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
let data = {
option: this.selectedOption
};
let loader = this.loading.create({
content: 'Processing please wait...',
});
loader.present().then(() => {
this.http.post('mydomain/fetch_data.php',data, options)
.map(res => res.json())
.subscribe(res => {
loader.dismiss()
this.items=res.server_response;
console.log(this.items);
this.items.map((item)=>{
this.val1.push(item.options);
});
this.items.map((item)=>{
this.val2.push(item.result);
});
});
});
this.showChart();
}
showChart(){
this.barChart = new Chart(this.barCanvas.nativeElement, {
type: 'bar',
data: {
labels: this.val1,
datasets: [{
label: '# of Votes',
data: this.val2,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
}
I got json data but to convert it to another array like labels: ["Red", "Brown", "Blue", "Yellow", "Green", "Purple", "Orange"], and data: [11, 15, 22, 4, 6, 2, 3] such that I can use it as val1 and val2 as shown above is my challenge.
Thank you in advance
First you install ng2-charts, and import { ChartsModule } from 'ng2-charts'; to app/app.module.ts
in example.html
<div style="display: block; color:white; responsive: true;
maintainAspectRatio: false;">
<canvas baseChart
height="350"
[colors]="chartColors"
[labels]="doughnutChartLabels"
[data]="doughnutChartData"
[chartType]="doughnutChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
in example.ts
export class ExamplePage {
doughnutChartLabels: string[] = [];
doughnutChartData: number[] = [];
doughnutChartType: string = 'pie';
checkChart : boolean;
...}
pushItem(){
#pushed your json data in doughnutChartData
#end called this fonction in ionViewDidLoad and any methods
}
public chartClicked(e:any):void {
#...
}
public chartHovered(e:any):void {
#...
}

Pull data from a json file and display it with a button

I am trying to pull data from a json file and display it, but I am unable to proceed with the program because I lack experience in coding Angular.
Currently using Angular 4.3, which uses HttpClientModule.
app.component.ts
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = '?';
data;
constructor(private http: HttpClient) {
}
ngOnInit(): void {
this.http.get('/src/app/students.json')
}
chgTab1() {
this.title = "Changed Title";
}
chgTab2() {
//Want to display the items from json file
}
}
students.json
[
{"id": "3", "mame": "Dama"},
{"id": "1", "mame": "ASD"},
{"id": "2", "mame": "Chris"},
{"id": "4", "mame": "Sass"},
]
import { Component, OnInit } from '#angular/core';
import { Http,Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = '?';
data;
showData = false;
constructor(private http: Http) { }
ngOnInit(): void {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.get('/assets/students.json', { headers: headers }).map(res => res.json()).subscribe(data => {
this.data = data;
})
}
chgTab1(){
this.title ="Changed Title";
}
chgTab2(){
//Want to display the items from json file
this.showData = !this.showData;
}
}
I have edited the whole thing. It will now work for you. Ensure you have the path to your student.json in the correct place.I moved it to the assets directory

Ionic 3 Accordion List with a Native Element Chart

I am trying to make an accordion list where when a user clicks on it, and it then displays a chart of data. The problem is the chart shows originally, but when I close the accordion list then it doesn't show again upon reopening. So basically open app, shows chart, click accordion element, chart disappears, click accordion element, it expands, but the chart doesn't show.
chart-page.html
<ion-header>
<ion-navbar>
<ion-title>Health Summary</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item padding (click)="toggleChartThisWeek(thisWeek)">
This Week
<div *ngIf="thisWeek">
<br>
<canvas #lineCanvas></canvas>
<br>
</div>
</ion-item>
</ion-list>
</ion-content>
chart-page.ts
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams, Platform } from 'ionic-angular';
import { Chart } from 'chart.js';
#IonicPage()
#Component({
selector: 'page-chart-page',
templateUrl: 'chart-page.html',
})
export class ChartPage {
#ViewChild('lineCanvas') lineCanvas;
lineChart: any;
chartLabels: any = ["January", "February", "March", "April", "May", "June", "July"];
chartData: any = [65, 59, 80, 81, 56, 55, 40];
thisWeek: any = true;
constructor(public navCtrl: NavController, public navParams: NavParams, public platform: Platform) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad HealthSummaryPage');
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: 'line',
data: {
labels: this.chartLabels,
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: this.chartData,
spanGaps: false,
}
]
}
});
}
ionViewWillEnter() {
}
toggleChartThisWeek() {
if(this.thisWeek) {
this.thisWeek = false;
} else {
this.thisWeek = true;
}
}
}
How do I get it to appear every time? Do I need to store it into a variable, and if so, how do I do that?
Check the code below which hopefully forces angular to redraw the template fully:
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams, Platform } from 'ionic-angular';
import { Chart } from 'chart.js';
#IonicPage()
#Component({
selector: 'page-chart-page',
templateUrl: 'chart-page.html',
})
export class ChartPage {
#ViewChild('lineCanvas') lineCanvas;
lineChart: any;
chartLabels: any = ["January", "February", "March", "April", "May", "June", "July"];
chartData: any = [65, 59, 80, 81, 56, 55, 40];
thisWeek: any = true;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public platform: Platform) {
}
ionViewDidEnter() {
console.log('ionViewDidEnter() HealthSummaryPage');
}
drawChart(){
if (! this.lineCanvas) { return; }
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: 'line',
data: {
labels: this.chartLabels,
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: this.chartData,
spanGaps: false,
}
]
}
});
}
toggleChartThisWeek() {
if(this.thisWeek) {
this.thisWeek = false;
} else {
this.thisWeek = true;
this.drawChart();
}
}
}