为什么我在订阅 patientAllergies observable 时会收到以下错误?

Why am I receiving the following error when subscribed to the patientAllergies observable?

当我select在patient-allergies.component.ts、select选项中添加patient allergy并点击save时,我收到如下错误:

错误错误:尝试区分“[object Object]”时出错。只允许数组和可迭代对象。

当我将对象从 rest-api.service.ts 通过 _patientAllergies.next() 传递到数组时,我无法理解为什么会收到此错误。

患者-allergies.component.html

<mat-card class="mat-typography">
  <mat-card-title>Allergies</mat-card-title>
  <mat-card-content>
    <hr>
    <div *ngFor="let patientAllergy of this.patientAllergies">
      <h3 *ngIf="!patientAllergy.nickname"> {{ patientAllergy.fullname }} </h3>
      <h3 *ngIf="patientAllergy.nickname"> {{ patientAllergy.fullname }} ({{ patientAllergy.nickname }}) </h3>
    </div>
  </mat-card-content>
  <mat-card-actions *ngIf="isEdit">
    <button mat-button class="dark" (click)="onAdd()">ADD</button>
    <button mat-button class="dark" (click)="onRemove()">REMOVE</button>
  </mat-card-actions>
</mat-card>

<mat-card *ngIf="isLoading" style="display: flex; justify-content: center; align-items: center">
  <mat-progress-spinner class="mat-spinner-color" mode="indeterminate"></mat-progress-spinner>
</mat-card>

患者-allergies.component.ts

import {Component, OnInit, Input, Pipe, PipeTransform} from '@angular/core';
import {RestAPIService} from 'src/app/rest-api.service';
import {ActivatedRoute} from '@angular/router';
import {MatDialog} from '@angular/material';

@Component({selector: 'app-patient-allergies', templateUrl: './patient-allergies.component.html', styleUrls: ['./patient-allergies.component.css']})
export class PatientAllergiesComponent implements OnInit {

    @Input()isEdit : boolean = false;

    constructor(private restAPIService : RestAPIService, private route : ActivatedRoute, public dialog : MatDialog) {}

    isLoading : boolean;
    patientAllergies;
    subscription = null;

    ngOnInit() {
        this.isLoading = true;
        this
            .restAPIService
            .getPatientAllergies(this.route.snapshot.params.id);

        this.subscription = this
            .restAPIService
            .patientAllergies
            .subscribe((patAllergies) => {
                this.patientAllergies = patAllergies as [];
                this.isLoading = false;
            });
    }

    onAdd() {
        let dRef = this
            .dialog
            .open(AllergiesDialogComponent, {
                disableClose: true,
                height: '800px',
                width: '600px',
                data: {
                    isAdding: true,
                    patientAllergies: this.patientAllergies
                }
            });

        dRef
            .afterClosed()
            .subscribe((res) => {
                res.forEach((ele) => {
                    this
                        .restAPIService
                        .addPatientAllergies(this.route.snapshot.params.id, ele.value.allergyID);
                });
            });
    }

    onRemove() {
        let dRef = this
            .dialog
            .open(AllergiesDialogComponent, {
                disableClose: true,
                height: '800px',
                width: '600px',
                data: {
                    isAdding: false,
                    patientAllergies: this.patientAllergies
                }
            });

        dRef
            .afterClosed()
            .subscribe((res) => {
                res.forEach((ele) => {
                    this
                        .restAPIService
                        .deletePatientAllergies(this.route.snapshot.params.id, ele.value.allergyID);
                });
            })
    }
}

import {Inject} from '@angular/core';
import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';
import {DialogData} from 'src/app/patient/patient.component';

@Component({selector: 'app-allergies-dialog', templateUrl: './allergies-dialog.component.html', styleUrls: ['./allergies-dialog.component.css']})
export class AllergiesDialogComponent implements OnInit {
    allergies = [];
    filterName : string;
    subscription;

    constructor(public dialogRef : MatDialogRef < AllergiesDialogComponent >, @Inject(MAT_DIALOG_DATA)public data : DialogData, private restAPIService : RestAPIService) {}

    ngOnInit() {
        this
            .restAPIService
            .getAllergies();

        if (this.data['isAdding']) {
            this.subscription = this
                .restAPIService
                .allergies
                .subscribe((allergies) => {
                    let allergiesArr = allergies as [];
                    this.allergies = [];

                    let patientAllergyNames = [];
                    this
                        .data['patientAllergies']
                        .forEach(patientAllergy => {
                            patientAllergyNames.push(patientAllergy['fullname'])
                        });

                    allergiesArr.forEach(allergy => {
                        if (!patientAllergyNames.includes(allergy['fullname'])) 
                            this.allergies.push(allergy);
                        }
                    );
                })
        } else {
            this.allergies = this.data['patientAllergies'];
        }
    }

    onClose(selectedOptions) {
        if (this.data['isAdding']) 
            this.subscription.unsubscribe();

        // either [] or the IDs of the objects to add/remove
        this
            .dialogRef
            .close(selectedOptions);
    }
}

@Pipe({name: 'filterOnName'})
export class filterNames implements PipeTransform {
    transform(listOfObjects : any, nameToFilter : string) : any {
        let allergyArr = listOfObjects as[];
        let matchedObjects = [];

        if (!listOfObjects) 
            return null;
        if (!nameToFilter) 
            return listOfObjects;

        allergyArr.forEach(allergyObj => {
            let fullname : string = allergyObj['fullname'];
            let nickname : string = allergyObj['nickname'];

            let fullnameLower = fullname.toLowerCase();
            let nicknameLower = fullname.toLowerCase();
            let filter = nameToFilter.toLowerCase();

            if (nickname) {
                if ((fullnameLower.includes(filter) || nicknameLower.includes(filter))) 
                    matchedObjects.push(allergyObj);
                }
            else {
                if (fullnameLower.includes(filter)) 
                    matchedObjects.push(allergyObj);
                }
            });

        return matchedObjects;
    }
}

休息-api.service.ts

    private _allergies;
    private allergiesSubject = new Subject();
    allergies = this
        .allergiesSubject
        .asObservable();

    private _patientAllergies;
    private patientAllergiesSubject = new Subject();
    patientAllergies = this
        .patientAllergiesSubject
        .asObservable();

getPatientAllergies(patientID) {
    const request = {
        headers: {},
        response: true
    };

    API
        .get('DiagnetAPI', '/v1/patients/' + patientID + '/allergies', request)
        .then(resp => {
            this._patientAllergies = resp.data;
            this
                .patientAllergiesSubject
                .next(this._patientAllergies);
        })
        .catch((err) => console.log(err))
}

addPatientAllergies(patientID, allergyID) {
    const request = {
        headers: {},
        response: true,
        body: allergyID
    };

    API
        .post('DiagnetAPI', '/v1/patients/' + patientID + '/allergies', request)
        .then(resp => {
            console.log(resp.data);
            this._patientAllergies = resp.data;
            this
                .patientAllergiesSubject
                .next(this._patientAllergies);
        })
        .then(() => {
           this.getPatientAllergies(patientID);
        })
        .catch((err) => console.log(err))
}

deletePatientAllergies(patientID, allergyID) {
    const request = {
        headers: {},
        response: true
    };

    API
        .del('DiagnetAPI', '/v1/patients/' + patientID + '/allergies/' + allergyID, request)
        .then((res) => console.log(res))
        .then(() => {
            this.getPatientAllergies(patientID);
        })
        .catch((err) => console.log(err))
}

如果 api 的响应不是数组而是对象,则可以在 *ngFor 循环中使用 keyvalue 管道。 在您的情况下 patientAllergy 将是一个具有两个键的对象, keyvalue 因此您可以像这样访问昵称: patientAllergy.value.nickname

您的模板:

<div *ngFor="let patientAllergy of this.patientAllergies | keyvalue">
   <h3 *ngIf="!patientAllergy.value.nickname"> {{ patientAllergy.value.fullname }} </h3>
   <h3 *ngIf="patientAllergy.value.nickname"> {{ patientAllergy.value.fullname }} ({{ patientAllergy.value.nickname }}) </h3>
</div>