简体   繁体   中英

How to make each angular component have a different array values

I have angular component which is displaying crypto currency prices from API. In the same service, I have an array of hard coded star rating values for each component. When I'm looping through each value from API, I also make an inside for loop to iterate through hard coded array of object literals and attach unique array value for rating for each crypto component. Older version (commented out) worked, but displayed same rating info for all crypto components. Now I commented it out and put more values in array to make it more simple. Here is the code. I don't get any errors, only undefined in console and rating component stops showing up in crypto component.

getProducts() {
        return this.http.get('https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,IOT,TRX&tsyms=USD')
  .map(result => {
    Object.keys(result).forEach(value => {

      // add logic to have each crypto a different rating
      var ratings = [{rating: 4, numOfReviews: 2}, {rating:5, numOfReviews: 3}, {rating:6, numOfReviews:1}];
      for(var i = 0; i < ratings.length; i++) {
        result[value]['ratingInfo'] = ratings[i].rating;
        result[value]['ratingInfo'] = ratings[i].numOfReviews;
      }

    /*  result[value]['ratingInfo'] = {
        imageUrl: "http://loremflickr.com/150/150?random=1",
        productName: "Product 1",
        releasedDate: "May 31, 2016",
        description: "Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.",
        rating: 4,
        numOfReviews: 2
      }*/
    });
    return result;
  });
}

Crypto.component.ts

import { Component } from '@angular/core';
import { ProductService } from './product.service';
import { RatingComponent } from './rating.component';
@Component({
  selector: 'crypto',
  styleUrls: ['./app.component.css'],
  template: `<h2 class="header">Crypto Price Compare</h2>
    <div *ngIf="cryptos">
    <div id="crypto-container" *ngFor="let crypto of objectKeys(cryptos)">
      <span class="left">{{ crypto }}</span>
      <span class="right">{{ cryptos[crypto].USD | currency:'USD':true }}</span>
      <br />
      <rating
      [rating-value]="cryptos[crypto].ratingInfo.rating"
      [numOfReviews]="cryptos[crypto].ratingInfo.numOfReviews">
  </rating>
    </div>
  </div>`
})
export class CryptoComponent {
  objectKeys = Object.keys;
cryptos: any;
ratings: any;

constructor(private _data: ProductService) {

}

ngOnInit() {
  this._data.getProducts()
    .subscribe(res => {
      this.cryptos = res;
      console.log(res);
    });

  //this.ratings = this._data.getRatings();
    console.log(this.ratings);


}

    onClick($event){
      console.log("Clicked",$event)
    }
}

You might want to change the implementation of your ProductService like this:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Injectable()
export class ProductService {

  constructor(private http: HttpClient) { }
  ...
  getProducts() {

    const ratings = [
      { rating: 4, numOfReviews: 2 }, 
      { rating: 5, numOfReviews: 3 }, 
      { rating: 6, numOfReviews: 1 },
      { rating: 7, numOfReviews: 4 }
    ];

    return this.http.get('https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,IOT,TRX&tsyms=USD')
      .pipe(
        map(
          cryptos => {
            const currencies = [];
            let index = 0;
            return Object.keys(cryptos).map((cryptoName, index) => {
              return {
                name: cryptoName,
                price: cryptos[cryptoName].USD,
                ratingInfo: { ...ratings[index] }
              }
            });
          }
        )
      )
  }
  ...
}

Doing this will result in the getProducts() method returning an Array of Objects that you can simply loop through in your view.

In your CryptosComponent Template, you can then do this:

<h2 class="header">Crypto Price Compare</h2>
  <div *ngIf="cryptos">
  <div id="crypto-container" *ngFor="let crypto of cryptos">
    <span class="left">{{ crypto.name }}</span> - 
    <span class="right">{{ crypto.price | currency:'USD' }}</span>
    <br />
    <rating
      [ratingValue]="crypto.ratingInfo.rating"
      [numOfReviews]="crypto.ratingInfo.numOfReviews">
    </rating>
  </div>
</div>

NOTE:

  1. I've changed the name of rating-value to ratingValue .
  2. This example uses Angular 7 where any operator that needs to be applied to an Observable needs to be pipe d through the pipe operator. If you're using Angular 4 or 5, you'll need to do it the same way you're doing as of now, by chaining .map to the Observable value.

Here's a Sample StackBlitz for your ref.

Not sure exactly what you want to do, but this doesn't make sense.

result[value]['ratingInfo'] = ratings[i].rating;
result[value]['ratingInfo'] = ratings[i].numOfReviews;

You are setting ratingInfo and immediately overwriting it with something else. Assuming ratingInfo is an object, you probably want something like this:

result[value]['ratingInfo']['rating'] = ratings[i].rating;
result[value]['ratingInfo']['numOfReviews'] = ratings[i].numOfReviews;

Or more simply:

result[value]['ratingInfo'] = ratings[i]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM