Как сделать, чтобы каждый угловой компонент имел разные значения массива

У меня есть угловой компонент, который отображает цены криптовалюты из API. В том же сервисе у меня есть массив жестко закодированных значений звездного рейтинга для каждого компонента. Когда я зацикливаюсь на каждом значении из API, я также создаю цикл for для итерации по жестко закодированному массиву литералов объекта и прикрепляю уникальное значение массива для оценки для каждого криптокомпонента. Старая версия (закомментированная) работала, но отображала одинаковую рейтинговую информацию для всех криптографических компонентов. Теперь я закомментировал это и поместил больше значений в массив, чтобы сделать его более простым. Вот код Я не получаю никаких ошибок, только неопределенный компонент консоли и рейтинг перестает отображаться в компоненте шифрования.

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)
    }
}

2 ответа

Решение

Возможно, вы захотите изменить реализацию вашего ProductService следующим образом:

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] }
              }
            });
          }
        )
      )
  }
  ...
}

Это приведет к getProducts() метод, возвращающий Array объектов, которые вы можете просто просмотреть в вашем представлении.

В своем шаблоне CryptosComponent вы можете сделать это:

<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>

НОТА:

  1. Я изменил имя rating-value в ratingValue,
  2. В этом примере используется Angular 7, где любой оператор, который должен быть применен к наблюдаемой, должен быть pipeчерез pipe оператор. Если вы используете Angular 4 или 5, вам нужно будет сделать то же самое, что и сейчас, с помощью цепочки .map Наблюдаемой стоимости.

Вот пример StackBlitz для вашей ссылки.

Не уверен, что именно вы хотите сделать, но это не имеет смысла.

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

Вы устанавливаете ratingInfo и немедленно перезаписываете его чем-то другим. Предполагая, что ratingInfo является объектом, вы, вероятно, хотите что-то вроде этого:

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

Или проще:

result[value]['ratingInfo'] = ratings[i]
Другие вопросы по тегам