Search code examples
javascriptangularngforrxjs-subscriptions

*ngFor simply not working with array of Objects


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!


Solution

  • 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