*ngFor simply not working with array of Objects

677 Views Asked by At

I have the TS code

getItems().subscribe(val=>{
this.items=val;
})

which works fine. When I console.log(this.items) I get

"array:0{size:XL,quantity:1}"

Buuut. Amazingly, something I've never dealt with before in angular, when I run the code in the html template of

<div *ngFor="let item of items">
{{item.size}}
</div

items =[{size:'XL',quantity:4}] I get ABSOLUTELY NOTHING. This is really bizzarre because I've written hundreds of these statements and have never had this issue before. Please help me.

Solved:

What I've figured out is that calling getItems() with a subject, where the getItems method returns a subject "asobservable" can ONLY be done in the same component, directly after the subject is populated. Populating a subject prior to page change seems to still allow the data to be transferred enough to log in console, but not to be usable by the greater application.

So therefore doing

updateItems(items);
getItemsUpdated().subscribe(val=>{
this.items=val
})

where there is a subject and

updateItems(items:items){
this.subject.next(items)
}
getItemsUpdated(){
return this.subject.asObservable()
}

would Work, but only when called directly next to each other in the same component.
Since in this case I was updating the subject, switching pages, and then calling the subject, I was experiencing a weird sort of subject limbo where the console was still able to record the value passed to the subject, but it was not being resolved fully by the receiving component, and therefore was not functioning with the *ngFor.

Correct Flow

updateItems(items);
---------->Navigate to next page-------->
getItemsUpdated().subscribe(val=>{
this.items=val
})

where there is a behaviorSubject and

updateItems(items:items){
this.behaviorSubject.next(items)
}

getItemsUpdated(){
return this.behaviorSubject.asObservable()
}

For this case, using a BehaviorSubject instead of Subject allowed the data to be process "on time" correctly and work with the app. Thanks everybody for your input!

2

There are 2 best solutions below

3
eko On BEST ANSWER

You should be using a BehaviorSubject or a ReplaySubject; plain Subject will only give you the values emitted after the subscription.

export class CartService {
  public cartUpdated: Subject<Item[]> = new BehaviorSubject([]);

More info in: Subject vs BehaviorSubject vs ReplaySubject in Angular

Fixed Stackblitz

2
ukn On

Your stackblitz doesnt allow ngFor so the setup must be wrong. Here is what I think is the problem:

Your app has a weird data flow, when you subscribe to your observable, you wont receive any data until something calls next on your subject. What you seems to be doing from what I've seen in your stackblitz is:

  1. Call to update which is going to to give a value to your Subject
  2. You subscribe and its already too late

You can't get the last value from a subject and since you subsribed too late, your console.log from the subscribe is never actually doing anything. You are seeing the console.log related to your update(the one from hello component)