I try to make a highchart app with Angular and API and i don't know why i get this error:ERROR TypeError: Cannot read property 'forEach' of undefined at DashboardComponent.GetProfitLossChart (47) .I don't have any errors in my code but i get this error in google chrome page.
This is my DashboardComponent.ts.
import { Component, OnInit } from '@angular/core';
import {Stockmodel} from '../model/stockmodel';
import { StockService } from '../services/stock.service';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import * as Highcharts from 'highcharts';
import { debug } from 'util';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboardponent.html',
styleUrls: ['./dashboardponent.css']
})
export class DashboardComponent implements OnInit {
addForm: FormGroup;
url: string = 'http://localhost:44311/api/GetStockData';
Stocks:Stockmodel[];
PortfolioStocks : Stockmodel[];
constructor(private stockService: StockService, private formBuilder: FormBuilder) {
}
ngOnInit() {
// this.GetActiveStocks();
this.GetDashboardPortfolioData();
}
GetDashboardPortfolioData()
{
this.stockService.GetStocks("http://localhost:44311/api/GetDashboardPortfolioData")
.toPromise().then(data => {
return this.PortfolioStocks = data;
});
}
public profitLossChart: any = {
chart: {
type: 'pie',
},
title: {
text: 'Profit/Loss Chart'
},
credits: {
enabled: false
},
series: [],
}
GetProfitLossChart(){
let totalInvestment:number=0;
let totalGain:number=0;
this.PortfolioStocks.forEach(row => {
totalInvestment+=row.TotalInvested;
totalGain += row.CurrentValue;
});
this.GetTopGainerChart();
this.GetTopLoserChart();
this.profitLossChart.series =[{
data: [{
name: 'Total Investment#',
y: totalInvestment,
},
{
name: 'Current Value',
y: totalGain,
}]
}]
Highcharts.chart('containerProfitLoss', this.profitLossChart);
}
public topGainerChart: any = {
chart: {
type: 'line',
},
title: {
text: 'Top Gainer'
},
credits: {
enabled: false
},
xAxis: {
categories: [],
},
yAxis: {
title: {
text: ''
},
},
series: [],
}
GetTopGainerChart() {
let length = this.PortfolioStocks.length;
if (length > 0) {
this.stockService.GetGainerLoserStockData('http://localhost:44311/api/GetGainerLoserStockData', this.
PortfolioStocks[length - 1].StockId, "Monthly")
.toPromise().then(data => {
const stockData = [];
const dates = [];
data.forEach(row => {
const temp_row = [
row.High,
];
dates.push(row.Date);
stockData.push(row.High);
});
var dataSeries = [];
for (var i = 0; i < stockData.length; i++) {
dataSeries.push(
stockData[i]
);
}
this.topGainerChart.series = [{ data: dataSeries, name:
this.PortfolioStocks[length - 1].StockId }]
this.topGainerChart.xAxis.categories = dates
Highcharts.chart('topGainerChart', this.
topGainerChart);
},
error => {
console.log('Something went wrong.');
});
}
}
public topLoserChart: any = {
chart: {
type: 'line',
},
title: {
text: 'Top Loser'
},
credits: {
enabled: false
},
xAxis: {
categories: [],
},
yAxis: {
title: {
text: ''
},
},
series: [],
}
GetTopLoserChart() {
let length = this.PortfolioStocks.length;
if (length > 0) {
this.stockService.GetGainerLoserStockData('http://localhost:44311/api/GetGainerLoserStockData',
this.PortfolioStocks[0].StockId, "Monthly")
.toPromise().then(data => {
const stockData = [];
const dates = [];
data.forEach(row => {
const temp_row = [
row.High,
];
dates.push(row.Date);
stockData.push(row.High);
});
var dataSeries = [];
for (var i = 0; i < stockData.length; i++) {
dataSeries.push(
stockData[i]
);
}
this.topLoserChart.series = [{ data: dataSeries,
name: this.PortfolioStocks[0].StockId }]
this.topLoserChart.xAxis.categories = dates
Highcharts.chart('topLoserChart', this.topLoserChart);
},
error => {
console.log('Something went wrong.');
});
}
}
}
I try to make a highchart app with Angular and API and i don't know why i get this error:ERROR TypeError: Cannot read property 'forEach' of undefined at DashboardComponent.GetProfitLossChart (47) .I don't have any errors in my code but i get this error in google chrome page.
This is my DashboardComponent.ts.
import { Component, OnInit } from '@angular/core';
import {Stockmodel} from '../model/stockmodel';
import { StockService } from '../services/stock.service';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import * as Highcharts from 'highcharts';
import { debug } from 'util';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.ponent.html',
styleUrls: ['./dashboard.ponent.css']
})
export class DashboardComponent implements OnInit {
addForm: FormGroup;
url: string = 'http://localhost:44311/api/GetStockData';
Stocks:Stockmodel[];
PortfolioStocks : Stockmodel[];
constructor(private stockService: StockService, private formBuilder: FormBuilder) {
}
ngOnInit() {
// this.GetActiveStocks();
this.GetDashboardPortfolioData();
}
GetDashboardPortfolioData()
{
this.stockService.GetStocks("http://localhost:44311/api/GetDashboardPortfolioData")
.toPromise().then(data => {
return this.PortfolioStocks = data;
});
}
public profitLossChart: any = {
chart: {
type: 'pie',
},
title: {
text: 'Profit/Loss Chart'
},
credits: {
enabled: false
},
series: [],
}
GetProfitLossChart(){
let totalInvestment:number=0;
let totalGain:number=0;
this.PortfolioStocks.forEach(row => {
totalInvestment+=row.TotalInvested;
totalGain += row.CurrentValue;
});
this.GetTopGainerChart();
this.GetTopLoserChart();
this.profitLossChart.series =[{
data: [{
name: 'Total Investment#',
y: totalInvestment,
},
{
name: 'Current Value',
y: totalGain,
}]
}]
Highcharts.chart('containerProfitLoss', this.profitLossChart);
}
public topGainerChart: any = {
chart: {
type: 'line',
},
title: {
text: 'Top Gainer'
},
credits: {
enabled: false
},
xAxis: {
categories: [],
},
yAxis: {
title: {
text: ''
},
},
series: [],
}
GetTopGainerChart() {
let length = this.PortfolioStocks.length;
if (length > 0) {
this.stockService.GetGainerLoserStockData('http://localhost:44311/api/GetGainerLoserStockData', this.
PortfolioStocks[length - 1].StockId, "Monthly")
.toPromise().then(data => {
const stockData = [];
const dates = [];
data.forEach(row => {
const temp_row = [
row.High,
];
dates.push(row.Date);
stockData.push(row.High);
});
var dataSeries = [];
for (var i = 0; i < stockData.length; i++) {
dataSeries.push(
stockData[i]
);
}
this.topGainerChart.series = [{ data: dataSeries, name:
this.PortfolioStocks[length - 1].StockId }]
this.topGainerChart.xAxis.categories = dates
Highcharts.chart('topGainerChart', this.
topGainerChart);
},
error => {
console.log('Something went wrong.');
});
}
}
public topLoserChart: any = {
chart: {
type: 'line',
},
title: {
text: 'Top Loser'
},
credits: {
enabled: false
},
xAxis: {
categories: [],
},
yAxis: {
title: {
text: ''
},
},
series: [],
}
GetTopLoserChart() {
let length = this.PortfolioStocks.length;
if (length > 0) {
this.stockService.GetGainerLoserStockData('http://localhost:44311/api/GetGainerLoserStockData',
this.PortfolioStocks[0].StockId, "Monthly")
.toPromise().then(data => {
const stockData = [];
const dates = [];
data.forEach(row => {
const temp_row = [
row.High,
];
dates.push(row.Date);
stockData.push(row.High);
});
var dataSeries = [];
for (var i = 0; i < stockData.length; i++) {
dataSeries.push(
stockData[i]
);
}
this.topLoserChart.series = [{ data: dataSeries,
name: this.PortfolioStocks[0].StockId }]
this.topLoserChart.xAxis.categories = dates
Highcharts.chart('topLoserChart', this.topLoserChart);
},
error => {
console.log('Something went wrong.');
});
}
}
}
Share
Improve this question
asked Jul 14, 2020 at 14:08
halsey321halsey321
672 silver badges9 bronze badges
3
- 1 Please check what this.PortfolioStocks value is when GetProfitLossChart() is called. Probably it is null or undefined. – Giannis Commented Jul 14, 2020 at 14:11
- you have horrible indexing – Ernesto Alfonso Commented Jul 14, 2020 at 14:17
- Thank you ,this.PortfolioStocks was null. – halsey321 Commented Jul 14, 2020 at 14:29
3 Answers
Reset to default 2I'm not sure here, but you don't have a safe check for data
that is returned by the promise. Is that where the error happens? if data
is undefined, data.forEach
will throw an error.
try to debug
.toPromise().then(data => {
//console.log(data)
)}
maybe response body something inside like
{
data: {},
status: 200
}
so you need to accses data via:
.toPromise().then(data => {
//console.log(data?.data)
)}
You are setting the PortfolioStocks
in a async method, this mean that you are not sure if the value are set in the moment you do the forEach
.
I advise you to use a BehaviorSubject
approach and rxjs
.
...
PortfolioStocks = new BehaviorSubject<Arry<Stockmodel>([]);
...
GetDashboardPortfolioData() {
this.stockService.GetStocks("http://localhost:44311/api/GetDashboardPortfolioData")
.toPromise().then(data => {
this.PortfolioStocks.next(data);
});
}
...
this.PortfolioStocks.pipe(filter(portfolioStocks => Array.isArray(portfolioStocks)))
.subscribe(portfolioStocks => {
portfolioStocks.forEach(row => {
totalInvestment+=row.TotalInvested;
totalGain += row.CurrentValue;
});
})