EDIT: DEMO OF THE NON-WORKING CODE
I'm having issues with using the async pipe on an observable. It works in one app but not the other.
The working one can be found here: https://stackblitz.com/edit/angular-ry1dev
The non-working code:
products.component.ts:
export class ProductsComponent implements OnInit {
products$: Observable<Product[]>;
//NOTE: this service is coming from Akita state management
constructor( private productService: ProductService ) {}
ngOnInit() {
this.products$ = this.productService.getProducts();
}
}
products.service.ts (Akita state management):
@Injectable({ providedIn: 'root' })
export class ProductService {
constructor( private prodStore: ProductStore, private prodService: ProductsService ) {}
getProducts() {
return this.prodService.getProducts().pipe(
tap( result => {
let dataArr = [];
for (let obj in result) {
dataArr.push(result[obj]);
}
this.prodStore.add(dataArr)
})
)
}
}
products.service.ts (http called by prodService above):
getProducts() {
return this.http.get<Product[]>(`${this.API}/products`);
}
products.component.html:
<mat-accordion *ngIf="products$" class='product-accordion'>
<mat-expansion-panel *ngFor="let product of products$ | async">
<mat-expansion-panel-header>
SKU: {{ product.sku }}
</mat-expansion-panel-header>
<p>${{ product.price }}</p>
<p>{{ product.description }}</p>
</mat-expansion-panel>
</mat-accordion>
The above app's store and query components are the same as the stackblitz.
I should be getting a list of products like the list of todos in the stackblitz but it's erroring in the HTML with:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
Why is it working on stackblitz but not in my app?
Could you check what's the actual response from your back-end? Your front-end's assumption is to fetch an array but seems like your back-end is responding with something like this:
{
"something": {},
"something": {}
}
the response should be an array instead, like this:
[
"something": {},
"something": {}
]
EDIT: If we can not change the backend behavior. Then we need to update our getProducts method to return what our async products binding requires.
getProducts() {
return this.prodService.getProducts().pipe(
map( result => {
let dataArr = [];
for (let obj in result) {
dataArr.push(result[obj]);
}
this.prodStore.add(dataArr);
return dataArr;
})
)
}