Tall Paul
Tall Paul

Reputation: 55

Have realtime updates for a single Firestore document

There is a lot of documentation and examples of firestore collections getting realtime updates. However, there is very little for those who wish to have a single document have real time updates. I want to have a single document (an item), on a page where only the item will be viewed and manipulated and any changes to document, will have realtime updating.

Here is my component that wants to do stuff with the item:

import { Component, OnInit } from '@angular/core';
import { ItemsService } from '../shared/items.service';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-view-item',
  templateUrl: './view-item.component.html',
  styleUrls: ['./view-item.component.css']
})
export class ViewItem implements OnInit {
  item;
  private sub: any;

  constructor(
    // Service used for Firebase calls
    private itemsService: ItemsService,
    private route: ActivatedRoute,
    private router: Router
  ) {}

  ngOnInit() {
    // Item retrieved from */item/:id url
    this.sub = this.route.params.subscribe(params => {
      this.getItem(params['id']);
    });
  }

  getItem = (id) => {
    this.itemsService.getItem(id).subscribe(res => {
      console.log(res);
      this.item = res;
      console.log(this.item);
    });
  }

And the service it uses for calls:

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';

@Injectable({
  providedIn: 'root'
})
export class ItemsService {
  constructor(
    private firestore: AngularFirestore
  )

  getItem(id) {
    return this.firestore.collection('items').doc(id).snapshotChanges();
  }
}

The log I get for console.log(this.item) is undefined. Calling this.item in the console returns the same. I am unsure of how to proceed and would appreciate any guidance. Logging res in the console returns a byzantine object. Perhaps that's how I access the item, but if so, why is it not saved in this.item and how do I access the item's values?

Upvotes: 0

Views: 460

Answers (1)

Julian W.
Julian W.

Reputation: 1571

snapshotChanges returns an observable of actions, not the actual value. You should extract the value with action.payload.doc.data():

So your code should look like the following example.

getItem(id) {
  return this.firestore.collection('items').doc(id).snapshotChanges()
    .pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return { id, ...data };
      })
    );
}

Or you can use valueChanges of doc.

getItem(id) {
  return this.firestore.collection('items').doc(id).valueChanges();
}

Upvotes: 2

Related Questions