【问题标题】:Read out Objects of an Observable in a Service in Angular在 Angular 的服务中读取 Observable 的对象
【发布时间】:2020-03-18 10:22:36
【问题描述】:

card.service.ts

@Injectable({
providedIn: 'root'
})

export class CardService {
drugs: Drugs = [];

public objObservable: any;
private objObserver: any;

constructor() {
    this.objObservable = new Observable((localObserver) => {
        this.objObserver = localObserver; // Convert this.objObserver from any to an observer object
        this.objObserver.next(this.drugs); // Connect this.drugs to observable object by observer
    });
}

getDrugs(): Observable<Drugs> {
    return this.objObservable;
}

addDrug(newDrug: Drug) {
    this.drugs = [...this.drugs, newDrug];
    return this.objObserver.next(this.drugs);
}

removeDrug(neo4jId: string) {
    this.drugs = this.drugs.filter((item: Drug) => item.neo4jId !== neo4jId);
    return this.objObserver.next(this.drugs);
}

我正在使用此服务在我的 Home 组件中的 Observable 中添加和删除一些药物。 在卡片组件中,我想在这个 Observable 中循环并给出我需要在 html 中显示的值。

card.component.html

<div>
{{  this.cardService.getDrugs() | async | json }}
</div>

这个给了我所有 observable 的输出为 json,然后我尝试做类似的事情

<div>
{{  (this.cardService.getDrugs() | async | json).type }}
</div>

只显示类型,但这不起作用。 我怎样才能遍历这个 observable 中的所有对象并只输出 f.e. 的类型?

药物型号:

export interface Drug {

neo4jId?: string;
drugId?: string;
tradingName: string;
type: string;
quantity: number;
expire: Date;
entryDate: Date;
lastModified?: Date;
slot: number;
substances?: Substance[]
};

export interface Drugs extends Array<Drug> { }

【问题讨论】:

  • 有点不清楚。 drugs: Drugs = [];Drugs 类型的数组。或者它是否意味着drugs = Drug[]Drug 类型的数组?

标签: angular asynchronous observable


【解决方案1】:

我通常使用 BehaviorSubject 来完成您想要完成的任务。 看看这是否适合你。你可以在这里查看一个工作示例https://stackblitz.com/edit/ng-service-behaviorsubject

import { Injectable } from '@angular/core'
import { BehaviorSubject, Observable } from 'rxjs';

export interface Drug {
  neo4jId: string;
  Description: string;
}

@Injectable({
  providedIn: 'root'
})
export class CardService {
  private bsDrugs = new BehaviorSubject<Drug[]>([])

  constructor() {
  }

  getDrugs(): Observable<Drug[]> {
      return this.bsDrugs;
  }

  addDrug(newDrug: Drug) {
      let drugs = [...this.bsDrugs.value, newDrug];
      this.bsDrugs.next(drugs);
  }

  removeDrug(neo4jId?: string) {
    let drugs = [];
    if (neo4jId) {
      drugs = this.bsDrugs.value.filter((item: Drug) => item.neo4jId !== neo4jId);
    } else {
      if (this.bsDrugs.value.length > 0 ) {
        this.bsDrugs.value.pop();
        drugs = this.bsDrugs.value;
      }
    }

    this.bsDrugs.next(drugs);
  }
}

【讨论】:

  • 我只是在问如何在我的 html 中输出它。在我的服务中一切正常
【解决方案2】:

分离drugs 容器是否有任何特定目的并且可以观察到?请检查以下是否满足要求

@Injectable({
 providedIn: 'root'
})
export class CardService {
 private drugsSource = new BehaviorSubject<Array<Drug>>([]);
 private drugs$ = this.drugsSource.asObservable();

 constructor() { }

 getDrugs(): any {
   return this.drugs$;
 }

 addDrug(newDrug: Drug) {
   this.drugsSource.next([...this.drugsSource.getValue(), newDrug]);
 }

 removeDrug(neo4jId: string) {
   this.drugsSource.next(this.drugsSource.getValue().filter((item: Drug) => item.neo4jId !== neo4jId));
 }
}

当有单独的 get 方法时,从 add 和 remove 方法返回 obserables 没有多大意义。因此,无论何时添加或删除值,都要订阅它。

组件

this._cardService.addDrug(drug);
this._cardService.getDrugs().subscribe(drugs => { 
  // handle value 
});

// similarly for removing
this._cardService.removeDrug('34');
this._cardService.getDrugs().subscribe(drugs => { 
  // handle value 
});

更新 要在 HTML 中显示类型,您需要编写一个管道。

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'drugsType'
})
export class TypeOfPipe implements PipeTransform {

  transform(drugs: any): any {
    let result = [];
    for (const drug of drugs) {
      let obj = {};
      for (const key of Object.keys(drug)) {
        obj[key] = typeof drug[key];
      }
      result.push(obj);
    }
    return result;
  }

}

工作示例:Stackblitz

【讨论】:

  • 服务运行良好,我只是想知道如何在我的 html 中输出 observable 的内容
  • 如果不看Drugs 模型的结构,这很难说。您能否更新问题中的模型?
  • 我在描述中添加了药物模型,有帮助吗?
  • 是的,你能创建一个你想在 HTML 中显示的模型吗?
  • HTML 中没有类型运算符。见here。你需要一个自己写的管道。我已经更新了答案。
【解决方案3】:

我解决了这样的问题

@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.css']
})
export class CardComponent implements OnInit {
  drugList: Observable<Array<Drug>>;
  subscription: Subscription;

constructor(private cardService: CardService) { }

ngOnInit() {

 this.drugList = this.cardService.getDrugs();

}

}

在html中

<div *ngFor="let drug of drugList | async">
  <p>{{   drug.tradingName    }}</p>
  <p>{{   drug.type  }}</p>
  <p>{{   drug.quantity  }}</p>
  <p>{{   drug.slot  }}</p>
</div>

风格当然可以做得更好。 我的意思是如何访问 Observable 中的对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2021-03-25
    • 2020-05-25
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    相关资源
    最近更新 更多