简体   繁体   English

在 Angular Firestore 中引用文档上的字段

[英]Referencing a field on document in Angular Firestore

I'm trying to reference one of the fields of a document in the component.ts file.我正在尝试引用 component.ts 文件中文档的字段之一。 The code below works, as long as I explicitly declare let day = "Sunday" .只要我明确声明let day = "Sunday" ,下面的代码就可以工作。

As there is a field "day" in this.meter, I would like to be able to declare let day = this.meter.day instead.由于 this.meter 中有一个字段“day”,我希望能够声明let day = this.meter.day I know that I have to somehow subscribe to this.meter , but I'm lost as to how.我知道我必须以某种方式订阅this.meter ,但我不知道如何订阅。

I've gone through all the documentation, and I'm completely overwhelmed and very confused, as this should be a relatively simple operation.我已经浏览了所有文档,我完全不知所措并且非常困惑,因为这应该是一个相对简单的操作。

Thank you.谢谢你。

import { Component, OnInit, ViewChild, ElementRef, HostListener, AfterViewInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument, AngularFirestoreCollection, AngularFirestoreCollectionGroup } from '@angular/fire/firestore';
import { Observable, Subscriber } from 'rxjs';
import { ActivatedRoute } from '@angular/router';

export interface Meter { meter: string; units: number; lastupdated: string; year: string; month: string; day: string; monthday: string}

@Component({
  selector: 'app-meter',
  templateUrl: './meter.component.html',
  styleUrls: ['./meter.component.scss']
})

export class MeterComponent implements OnInit {
  meterId: string;
  private meterDoc: AngularFirestoreDocument<Meter>;
  meter: Observable<Meter>;
  dailydata: Observable<any>;
  todayinweek: Observable<any>;
  pastweek: Observable<any>;
  day: string;

  constructor(
    private route: ActivatedRoute, private db: AngularFirestore, private afs:AngularFirestore) {
    this.meterId = this.route.snapshot.paramMap.get('id');
    this.meter = this.afs.doc<Meter>(`meters/${this.meterId}`).valueChanges();
    }

ngOnInit() {


**//let day = this.meter.day;**
let day = "Sunday";


 this.dailydata = this.db.collection('meters').doc<any>(this.meterId).collection('dailydata').doc(day).valueChanges();
 this.todayinweek = this.db.collection('meters').doc<any>(this.meterId).collection(('meterdata'), ref=> ref.where("day", "==", day).limit(10)).valueChanges();
 this.pastweek = this.db.collection('meters').doc<any>(this.meterId).collection(('meterdata'), ref=> ref.orderBy("date", "desc").limit(7)).valueChanges();

 }

}

I've tried following Get field from Firestore document , but it didn't work for me.我试过从 Firestore 文档中获取字段,但它对我不起作用。 I received an error that "Property 'then' does not exist on type 'Observable'"我收到一条错误消息,指出“'Observable' 类型上不存在属性 'then'”

You can make every variable an observable, and just let the data stream through your component :)您可以将每个变量都设置为可观察的,只需让数据流通过您的组件:)

First you get the current id from the route param observable and with this you get the meter angularfire collection with the id.首先,您从路由参数 observable 中获取当前 id,然后您将获得带有 id 的 Meter angularfire 集合。

Then from this id combined with the meter observable, you can get all the other values.然后从这个 id 结合仪表 observable,你可以获得所有其他值。

readonly meterDoc = this.route.paramMap.pipe(
  map((params) => params.get('id')),
  distinctUntilChanged(),
  map((id) => this.db.collection('meters').doc<Meter>(id)),
  shareReplay({ refCount: true, bufferSize: 1 })
);

readonly meter = this.meterDoc.pipe(
  map((meter) => meter.valueChanges())
);

readonly docMeter = combineLatest([
  this.meterDoc,
  this.meter
]);

readonly dailydata = this.docMeter.pipe(
  switchMap(([ doc, meter ]) => doc.collection('dailydata').doc(meter.day).valueChanges())
);

readonly todayinweek = this.docMeter.pipe(
  switchMap(([ doc, meter ]) => doc.collection(
    'meterdata',
    ref => ref.where("day", "==", meter.day).limit(10)
  ).valueChanges())
);

readonly pastweek = this.meterDoc.pipe(
  switchMap((doc) => doc.collection(
    'meterdata',
    ref => ref.orderBy("date", "desc").limit(7)
  ).valueChanges())
);

untested code though虽然未经测试的代码


As you are reluctant to move everything to streams, even though, all the data you have is async.由于您不愿意将所有内容移动到流中,即使您拥有的所有数据都是异步的。 But luckily for you there are other options.但幸运的是,您还有其他选择。 You can use a route resolver to get the meter, and read this in your component:您可以使用路由解析器来获取仪表,并在您的组件中读取:

@Injectable({ providedIn: 'root' })
export class MeterResolve implements Resolve<Meter> {
  resolve(route: ActivatedRouteSnapshot): Observable<Meter> {
    return this.db.collection('meters')
      .doc<Meter>(route.params.id)
      .valueChanges()
      .pipe(
        take(1)
      );
  }
}

Add this to your id route:将此添加到您的 id 路由:

{ route: 'meter/:id', component: MeterComponent, resolve: { meter: MeterResolve } } 

You can then read this in your component:然后您可以在您的组件中阅读此内容:

readonly meterId = this.route.snapshot.params.id;
readonly meter = this.route.snapshot.data.meter;
readonly meterDoc = this.db.collection('meters').doc<Meter>(this.meterId);
readonly dailydata = this.meterDoc.collection('dailydata').doc(this.meter.day).valueChanges();
readonly todayinweek = this.meterDoc.collection(
    'meterdata',
    ref => ref.where("day", "==", this.meter.day).limit(10)
  ).valueChanges();
readonly pastweek = this.meterDoc.collection(
    'meterdata',
    ref => ref.orderBy("date", "desc").limit(7)
  ).valueChanges();

If for some reason, you don't even want to use resolvers, you can also do a subscribe in your ngOnInit, and go from there.. but.. please don't :) (this is based on the code in your question)如果由于某种原因,你甚至不想使用解析器,你也可以在你的 ngOnInit 中订阅,然后从那里开始......但是......请不要:)(这是基于你问题中的代码)

ngOnInit() {
  this.meter.pipe(
    take(1)
  ).subscribe(({ day }) => {
    this.dailydata = this.db.collection('meters').doc<any>(this.meterId).collection('dailydata').doc(day).valueChanges();
    this.todayinweek = this.db.collection('meters').doc<any>(this.meterId).collection(('meterdata'), ref=> ref.where("day", "==", day).limit(10)).valueChanges();
    this.pastweek = this.db.collection('meters').doc<any>(this.meterId).collection(('meterdata'), ref=> ref.orderBy("date", "desc").limit(7)).valueChanges();  
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM