I'm using Angular and AngularFire to get data from my Firestore Database.
I have two services 'itemsService', 'detailsItemService' which collect and return data from my Firestore collection 'items' and 'detailsItem';
// it's the same for detailsItemService
[...]
export class itemsService {
private items: Observable<Item[]>;
constructor(
private db: AngularFirestore,
private userService: userService
) {
this.items = db.collection<Item>(
'items',
ref => ref.where('userID', '==', this.userService.userID)
)
.snapshotChanges()
.pipe(
map(array => {
return array.map(item => {
return {
uid: item.payload.doc.id,
...item.payload.doc.data()
} as Item;
});
});
);
}
getItems() {
return this.applications;
}
}
Then in my controller 'itemsCtrl', I make a subscription to get my 'Items' with uid and I proceed to a forEach to make a subscription 'detailsItem' of each Item with its uid.
[...]
export itemsCtrl implements OnInit {
public items = [];
constructor(
private itemsService: itemsService
) {
const items = [];
this.itemsService.getItems().subscribe(items => {
items.forEach((item, key) => {
items[key] = item;
this.detailsItemService.getDetails(item.uid).subscribe(details => {
items[key].details = details;
});
}
this.items = items;
});
}
[...]
}
But in my view, I got undefined properties when the page starts to load.
<div *ngFor="let item of items">
<input [(ngModel)]="item.details.name">
</div>
Then I get this error :
ERROR TypeError: Cannot read property 'name' of undefined
where undefined id 'details'
Thanks for helping :')
Use this.items directly (getDetails is async function and this.items = items will be evaluated before the subscription is completed):
this.itemsService.getItems().subscribe(items => {
items.forEach((item, key) => {
this.items[key] = item;
this.detailsItemService.getDetails(item.uid).subscribe(details => {
this.items[key].details = details;
});
}
});
And check if details exists:
<input *ngIf="item.details" [(ngModel)]="item.details.name">