I am developing a cryptocurrencies tracker app using angular, most of my code is finished. I have already displayed a list with 3 crypto currencies and their name, price, 24h % change etc and I am using the Messari API to retrieve the data(https://data.messari.io/api/v1/assets). This API provides a set of 20 currencies in total and I have implemented an add button so when the users click it another currency will be displayed on the list. But I am having a problem, because every time I try to test the function, which I have provided below:
addCrypto() {
// Check if cryptoToAdd is not empty
if (!this.cryptoToAdd) {
console.log('Error: Please enter a cryptocurrency symbol.');
return;
}
// Fetch cryptocurrency data from the API based on 'cryptoToAdd'
this.cryptoService.getCryptoDetail(this.cryptoToAdd).subscribe(
(cryptoData: any) => {
if (cryptoData && cryptoData.data) {
const cryptoToAdd = cryptoData.data;
// Check if the cryptocurrency is already in the list
const isCryptoInList = this.cryptoList.some(
(crypto) => crypto.id === cryptoToAdd.id
);
if (!isCryptoInList) {
// Ensure the necessary properties are available
if (!cryptoToAdd.metrics || !cryptoToAdd.metrics.all_time_high) {
console.log('Cryptocurrency data is incomplete.');
return;
}
// If not in the list, add it
this.cryptoList.unshift(cryptoToAdd); // Add to the beginning of the list
this.cryptoService.addCrypto(cryptoToAdd);
this.cryptoToAdd = ''; // Clear the input field
} else {
console.log('Cryptocurrency is already in the list.');
}
} else {
console.log('Cryptocurrency data not found.');
}
},
(error) => {
console.error('Error fetching cryptocurrency details:', error);
}
);
}
it gives me this ERROR TypeError: Cannot read properties of undefined (reading ‘all_time_high’). I don’t understand what the problem may be, because I have accessed this property and displayed it in the 3 currencies that are already being shown on the list.
crypto-list.component.html
<div >
<div class="custom-toolbar">
<mat-toolbar class="custom-toolbar">
<span >Crypto List</span>
<span class="example-spacer"></span>
<input matInput class="add" type="text" [(ngModel)]="cryptoToAdd" placeholder="Add currency by name" >
<button class= "add-button" (click)="addCrypto()">Add</button>
</mat-toolbar>
</div>
<ul>
<li *ngFor="let crypto of cryptoList" class="crypto-list">
<img [src]="iconPath + crypto.symbol.toLowerCase() + '.png'" alt="{{ crypto.name }} Icon" class="crypto-icon" />
<div class="crypto-info">
<h3 class="crypto-name">{{ crypto.name }}</h3>
<h3 class="crypto-symbol">{{ crypto.symbol }}</h3>
</div>
<div class="crypto-info">
<p class="price">${{ crypto.metrics.all_time_high.price| number: '1.2-2' }}</p>
<p [ngClass]="{'negative': crypto.metrics.market_data.percent_change_usd_last_24_hours < 0,
'positive': crypto.metrics.market_data.percent_change_usd_last_24_hours >= 0}">
{{ crypto.metrics.market_data.percent_change_usd_last_24_hours | number: '1.2-2' }}%
<span [ngClass]="{'up-arrow': crypto.metrics.market_data.percent_change_usd_last_24_hours >= 0, 'down-arrow': crypto.metrics.market_data.percent_change_usd_last_24_hours < 0}">
</span>
</p>
</div>
<button (click)="removeCrypto(crypto.id)" [disabled]="cryptoList.length === 0">Remove</button>
</li>
</ul>
</div>
And this is the service I am using to communicate with the API:
crypto.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class CryptoService {
private apiUrl="https://data.messari.io/api/v1";
private cryptoList: any[] = []; // To store the list of cryptocurrencies
constructor(private http: HttpClient) {}
getCryptoList(): Observable<any> {
return this.http.get(`${this.apiUrl}/assets`);
}
getCryptoDetail(id: string): Observable<any> {
return this.http.get(`${this.apiUrl}/assets/${id}/metrics`);
}
// Method to store the list of removed cryptocurrencies
storeRemovedCryptos(removedCryptos: string[]): void {
localStorage.setItem('removedCryptos', JSON.stringify(removedCryptos));
}
// Method to retrieve the list of removed cryptocurrencies from local storage
getRemovedCryptos(): string[] {
const removedCryptosJson = localStorage.getItem('removedCryptos');
return removedCryptosJson ? JSON.parse(removedCryptosJson) : [];
}
// Implement methods to add and remove cryptocurrencies
addCrypto(crypto: any) {
this.cryptoList.push(crypto);
}
removeCrypto(id: string) {
if (this.cryptoList.length === 0) {
console.log('CryptoList is empty. Cryptocurrency cannot be removed.');
return;
}
console.log('Removing cryptocurrency with ID:', id);
console.log('Current cryptoList:', this.cryptoList);
const index = this.cryptoList.findIndex(crypto => crypto.id === id);
if (index !== -1) {
console.log('Found cryptocurrency at index:', index);
this.cryptoList.splice(index, 1);
console.log('Cryptocurrency removed.');
} else {
console.log('Cryptocurrency not found in the list.');
}
}
}
I tried to check if cryptoData
contains valid data and if the required properties (metrics
and metrics.all_time_high.price
) exist and are not undefined and if the data is complete, the cryptocurrency is added to the list. Otherwise, it logs the “Cryptocurrency data is incomplete” error message. This was to help me understand better what the problem may be, but still I can’t figure it out.
Any help would be much appreciated.
You need to add your code, the community will not be able to help you with the given information.
Sorry, I was editing it. Now it’s up. Thank you
Can you share your code in a Stackblitz link?
@ManishGiri sure thing stackblitz.com/edit/angular-quqrzc?file=src%2Fmain.ts
@Rea Compiler error in your code,
add-currency
component seems to be missingShow 1 more comment