0

I have created a small application for keeping track of how much time I spend in different courses (as a teacher) using Angular 5 and putting my data in Firestore via AngularFire2. Most things have worked out nicely, but for the final part of the application I am having serious problems. I am quite a newbie at Angular/Firebase and most importantly (perhaps) with reactive programming.

The data that is stored in Firestore is quite simple: Data stored in Firebase It consists of six fields for information about the course, when the course was held and most importantly what I did (called Element) and for how long (called Duration).

Now, what I would like to do is to make a report that summaries all the durations for each thing I did (Element). In essence, what I would like to do is the equivalent of a GroupBy in SQL. As I understand it Firebase does not have an operation for grouping.

My, so far failed approach to this, has been to try to create an array into which I put the data and make calculations on that. It is here that I fail.

My first attempt is based on creating an observer as most examples for retrieving data in tutorials use. WorkItem is a simple class that has the same content as in Firebase.

this.lectureDoc = this.afs.collection(`users/${this.afAuth.auth.currentUser.uid}/regTime`,
ref => ref.where('course', '==', this.selectedCourse.courseName).orderBy('element') );

this.lectureItems = this.lectureDoc.snapshotChanges().pipe(
  map (courses => courses.map(a => {
  const data = a.payload.doc.data() as WorkItem;
  const id = a.payload.doc.id;
  return { id, ...data };
  })
));

this.lectureItems.subscribe(item => { 
  item.forEach(i => {
    this.allElements.push(i);
  });
});

console.error(this.allElements);
console.error(this.allElements[0]);

The two last lines show the problem, namely that the first (of the two last lines) will return the complete array while the second will return 'undefined'.

I understand that reactive programming will make asynchronous calls and that I therefore cannot know for sure when the data is filled. However, I do not understand why I can see the content of the array in the first of the two last lines, but not in the second.

My second attempt is based on getting the data from the documents of the collection itself and also, to prevent empty arrays, using .then() but again the two last lines show exactly the same output as previously.

this.lectureDoc.ref.get().then(item => {
 item.forEach(i => {
  this.lectures.push(i.data() as WorkItem);
 });
});

console.error(this.lectures);
console.error(this.lectures[0]);

The output can be seen in this image: Output from the running program

So, to recap, what I would like to do is to collect all the data in an array of WorkItem and then calculate how much time has been spent on different tasks and then display it in list on the web page. I have not come to the display part and I suspect that I will have trouble again with the array not being populated when bound to the list. I have a hard time to understand reactive programming...

Any help would be greatly appreciated!

//Tobias

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

2

This is a pretty common behaviour of the console as far as I'm aware, at least in Chrome. When you log data that's async but haven't been populated yet, the console will still show the array once the async operation is completed.

But when you log an object in the array, at the time that you log it that object isn't there yet, therefore the log will show as undefined.

Simply do the logging inside of the forEach and you will see the data being pushed properly.

An another case, example there: Console.log behavior

carton
  • 1,168
  • 9
  • 17
Chrillewoodz
  • 27,055
  • 21
  • 92
  • 175
  • Hi, thanks but I don't see how this helps... Yes, if I log inside of the forEach I can see it but it is still not "available" outside. I would like to manipulate the content and send it to a list in HTML, which is not possible since the array is seen as undefined. – Tobias Andersson Gidlund Jun 07 '18 at 13:43
  • Hi again -- actually, based on your explaination I think it works better than I think. I leave logging and try to use the array instead and so far it actually works better. Will experiment a little more to see if it is okay. But thanks! – Tobias Andersson Gidlund Jun 07 '18 at 14:07
  • Glad I could help a little :) – Chrillewoodz Jun 08 '18 at 06:07
  • 1
    Yes, it was exactly as you said -- everything actually worked but I was staring too much into the console... Thanks alot! – Tobias Andersson Gidlund Jun 08 '18 at 07:46