angular - Hur initierar och tilldelar jag korrekt ett observable med angulafire2?


Jag använder Angular 6 och Rxjs 6.

Följande kod kommer att ge undefined på ListFormsComponent om och om igen tills Observable tilldelas av getForms(), då kommer den att visa datan. getForms() anropas av navigeringstjänsten när man försöker navigera till ListFormsComponent-sidan.

FormService.ts

export class FormService {

  public forms$: Observable <Array<Form>> ;
  public assignedForms$: Observable <Array<Form>> ;
  public form$: Observable <Form>;
  constructor(
    private afs: AngularFirestore,
    private authService: AuthService,
  ) {}

  getForms() {
    let zippedData = zip(this.authService.user$);
    zippedData.subscribe(data => {
      this.forms$ = this.afs.collection('networks')
        .doc(data[0].activeNetworkProfile.id)
        .collection('companyProfiles')
        .doc(data[0].activeCompanyProfile.id)
        .collection<Forms>('inspectionForms')
        .valueChanges();
    })
  }

}

ListFormsComponent.ts

export class ListFormsComponent implements OnInit {
  public forms: Forms[];
  constructor(private formService: FormService, private navigateService: NavigationService) {

    this.formService.forms$.subscribe(forms => { //<---Error here this.formService.forms$ is undefined
      this.forms = forms;
      console.log("Forms inside component");
      console.log(this.forms);
    })
  }
}

ListFormsComponent.html

<mbsc-listview [options]="listSettings" style="display:none">
  <mbsc-listview-item (click)="viewDetails(form.id)" *ngFor="let form of forms">
    <h3 class="mbsc-lv-txt">{{form.name}}</h3>
    <p class="mbsc-lv-txt">{{form.lastEdited | date: 'medium'}} </p>
  </mbsc-listview-item>
</mbsc-listview>

NavigationService.ts

navigateForms() {
  this.formService.getForms();
  this.navigateService.navigate('forms');
}

Så jag bestämde mig då för att initiera observablen genom att göra följande kod (se nedan) i konstruktorn för FormService.ts och det stoppar felen men triggar inte prenumerationen i ListFormsComponent.ts. Jag antar att när valueChanges() returnerar Observable till forms$ så bryter det resten av prenumerationerna.

this.forms$ = new Observable<Array<Forms>>();

Svar #1

Så problemet är i den här funktionen:

navigateForms() {
  this.formService.getForms();
  this.navigateService.navigate('forms');
}

Du har anropat this.formService.getForms(); vilket kommer att initiera forms$ på FormService. Men samtidigt navigerar du också till forms vilket kommer att rendera ListFormsComponent. I din ListFormsComponent gör du formService.forms$ vilket kanske inte har initierats vid det tillfället. Därför får du det som undefined.

Istället för att använda forms$ skulle jag helt enkelt ha returnerat Observable-värdet från getForms-metoden och jag skulle ha kallat det i ListFormComponent:s ngOnInit-metod:

export class FormService {

  public forms$: Observable <Array<Form>> ;
  public assignedForms$: Observable <Array<Form>> ;
  public form$: Observable <Form>;
  constructor(
    private afs: AngularFirestore,
    private authService: AuthService,
  ) {}

  getForms() {
    return zip(this.authService.user$).pipe(
      flatMap(data => {
        return this.afs.collection('networks')
          .doc(data[0].activeNetworkProfile.id)
          .collection('companyProfiles')
          .doc(data[0].activeCompanyProfile.id)
          .collection<Forms>('inspectionForms')
          .valueChanges();
      })
    );
  }

}

Sedan i ListFormsComponent:

export class ListFormsComponent implements OnInit {
  public forms: Forms[];
  constructor(
    private formService: FormService, 
    private navigateService: NavigationService
  ) { }

  ngOnInit() {
    this.formService.getForms().subscribe(forms => {
      this.forms = forms;
      console.log("Forms inside component");
      console.log(this.forms);
    });
  }

}

Dessutom behöver jag inte kalla getForms från navigateForms nu. Så jag kan bli av med det:

navigateForms() {
  this.navigateService.navigate('forms');
}