Observable async in ngFor


#1

i have this method on my service

getPatients(): Observable<IPatient[]>{
        return this.http.get(this.PatientListUrl)
            .map((res: Response) => {
                this.patients = res.json();
                return this.patients;
            })
            .catch(this.handleError);
}

on my patients view i want to list them and update the view whe i delete one of them

  <ion-item-sliding #slidingItem *ngFor="let patient of patients">
    
     <ion-item>
     ....
    </ion-item>

    <ion-item-options side="right">
      <button ion-button color="danger" (click)="delete(slidingItem,patient)"><ion-icon name="trash"></ion-icon>Delete</button>
    </ion-item-options>

  </ion-item-sliding>

and on my patients.ts i have

patients: IPatient[];
....

  initializePatients() {
   this.patientsService.getPatients().subscribe(patients =>
         this.patients = patients,
         error => this.errorMessage = <any>error
     );
  }

....

  delete(slidingItem: ItemSliding,patient){

            this.patientsService.deletePatient(patient.patientId);
            this.initializePatients(); //TODO with ngfor async
        
  }

but when i delete one patient, the view is not updated (sometime happen)
i tried to put async in the ngfor, but i get error for the async pipe. ‘patients’ in the component must be observable?
there are other ways to sync the view with observables? thank you


#2

You don’t need the async pipe here. Angular’s change detection is pretty smart. Any time you assign to this.patients, it will be automatically reflected in the ngFor. You have a couple of options here, but first you need to make deletePatient return some sort of future (Promise or Observable) that resolves once it has completed successfully.

Then, you can either just reinitialize like you are doing:

this.patientsService.deletePatient(patient.patientId)
  .then(() => this.initializePatients());

…or you can manually update this.patients:

this.patientsService.deletePatient(patient.patientId)
  .then(() => {
    this.patients = this.patients.filter(p => p.patientId != patient.patientId));
  });

I suspect your “sometime happen” is the result of a race condition whereby you call getPatients again before the deletion has completed.