I've recently started developing using Angular, and I'm still in learning mode. So, I have this dilemma, which I need to access the "Length" property of an array inside of .Subscribe of an Observable; which I'm currently getting undefined. Strange, because I can see the Array values, but when calling Length I get undefined.
This is my code...
category: Observable<Category>;
categorySubject = new Subject<Category>();
categorySubscription: Subscription;
constructor(private db: AngularFirestore) { }
retreivingItems() {
this.fetchCategoryItems("").subscribe((items) => {
console.log(items.properties); // Properties are available
console.log('properties[] length = ' + items.properties.length); // output is still undefined
})
}
fetchCategoryItems(category: string) {
// Get data from firebase
return this.db
.collection('category')
.doc(category)
.get()
.pipe(
map((doc) => ({
id: doc.id,
...doc.data() as Category
}))
);
}
}
// Category & Property Model
export interface Category {
category_name: string,
properties: Array<Property>
}
export interface Property {
field_name: string,
field_tpye: string
}
I have also tries using a Subject to wrap the Observable, but I still get undefined.
My guess is that on the Subscribe, the category values hasn't still finished gathering all the streamed data... so how can I achieve this?
Output: undefined_output
A few things to clear out first:
db.collection().doc().get()
, you basically "prepare" the observable to emit data.Now, in your code, you have defined fetchCategoryItems
to store the observable in the category
property, which looks unnecessary. Since you are calling the Firestore database, it's a network call and is immediately completed upon successful response. So, you can modify this class in question (assuming it's a service provider) like the following:
@Injectable({ providedIn: 'root' })
export class CategoryService {
constructor(private readonly db: AngularFirestore) {}
fetchItems(category: string) {
return this.db.collection('category').doc(category).get().pipe(map((doc) => ({ id: doc.id, ...doc.data() })));
}
}
Notice how we have set it up to return an observable from fetchItems
method. All is left now is to subscribe to this observable and get the data. In the component file, you can do:
@Component({ /* ... */ })
export class CategoryComponent {
constructor(private readonly categoryService: CategoryService) {}
onFetch() {
this.categoryService.fetchItems().subscribe((items) => {
console.log(items.properties); // not `undefined`
console.log(items.properties.length); // it should be `4` according to your question
});
}
}