Отображение объекта JSON в наблюдаемый для использования с ngFor Angular - PullRequest
0 голосов
/ 26 февраля 2019

Я пытаюсь сопоставить объект JSON с наблюдаемым Интерфейсом, который я настроил в своем угловом приложении, я надеюсь, что после его сопоставления я смогу использовать его в качестве входного для циклического прохождения через ngFor.

К сожалению, я не верю, что я настраиваю либо свою службу правильно, либо, возможно, вызов службы.

Я получаю объект json, возвращенный как один объект, но ngFor не проходит должным образом через циклвозвращенные результаты, любая помощь в указании того, что я могу пропустить, будет принята с благодарностью.

// Интерфейс, к которому я пытаюсь получить доступ

export interface IProduct {
   name: string;
   description: string;
   price: number;
   category: string;
   image: string;
}

// Служба, которую я пытаюсь вызвать

private productList = new BehaviorSubject<IProduct[]|null>(null);
productListChanges$ = this.productList.asObservable();
constructor(private http: HttpClient) { }

getProds(): Observable<IProduct[]> {
     this.productList.next(null);
     return this.http.get<IProduct[]> 
                      ('http://localhost:4200/assets/data/products.json')
     .pipe(
        tap(data => this.productList.next(data)),
     );
 }

// Вызов службы

productsList: IProduct[] = [];

this.productService.getProds().subscribe((response: any) => {
  this.productsList = response.products[0] as IProduct[];
  console.log(this.productsList);
});

// Попытка использования ngFor с полученным объектом

<app-product *ngFor="let product of productsList" [prod]="product" ></app-product>

// Журнал консоли с выходов вызова службыследующий

logOutput из сервисного вызова

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

Я вижу, что вы используете HTTP для обслуживания данных JSON, которые легко доступны в виде данных, поступающих из статического файла, существующего в папке ваших ресурсов.Я бы избегал HTTP-звонков для их обслуживания.Я реорганизовал ваш код как для обслуживания статических данных, так и для поддержки удаленного запроса данных с использованием одного и того же метода обслуживания.Это также должно помочь во время модульного тестирования, так как асинхронное тестирование - это кошмар.

// Changed the Interface to a class
export class Product {
   name: string;
   description: string;
   price: number;
   category: string;
   image: string;
}

// Create a sample-data.ts file
export const ProductListData: Array<Product> = [
    {
       name: 'ProductName',
       description: 'Description',
       price: '9.99', // Maybe should be a number type and not string
       category: 'Test Category',
       image: 'your url for testing'
    }
]

// In service... 
import { of } from 'rxjs';
import { ProductListData } from './sample-data';
useSampleData = false;

getProducts(): Observable<Array<Product>> {
    if (useSampleData) {
        // Use this is your want to serve static JSON
        return of(ProductListData); // of() turns your readily avialable object into an obeservable promise
    } else {
    // Get from actual HTTP as async
        return this.http.get<Array<Product>>('http://localhost:4200/api/your-endpoint-url');
    }
 }
 
 
// In you Component...
public productList: Array<Product> = [];

this.productService.getProducts().subscribe(
    productList => {
      this.productsList = productList;
    },
    err => {
        console.log('Error: ', err);
    }
);

Ваш шаблон не нуждается в изменении.

0 голосов
/ 26 февраля 2019

Как показывает вывод вашей консоли, productsList - это Объект, но ngFor ожидает Массив.

Если вы можете изменить данные, легко можно изменить их на Массив ([...]) вместо Объекта ({...}).

В противном случае у вас есть несколько вариантов преобразования структуры в коде в массив.Например, при использовании Object.values() вы можете преобразовать вашу текущую структуру в массив.Кроме того, вы также можете использовать KeyValuePipe , доступную начиная с Angular 6.1.Также здесь ответили https://stackoverflow.com/a/51491848/9999800

0 голосов
/ 26 февраля 2019

Попробуйте использовать асинхронный цикл с Observables.

<app-product *ngFor="let product of productsList | async" [prod]="product" ></app-product>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...