【问题标题】:How to use an observable without subcribe in Angular如何在 Angular 中使用 observable 而不订阅
【发布时间】:2019-09-25 12:30:24
【问题描述】:

我有一个 Angular 8 应用程序,我正在使用这样的 API 调用:

getDossierEntry(patientUUID: string,   type: String = '' ): Observable<DossierEntry[]> {
  const entryType = type === '' ? 'all' : 'type/' + type;
  return this.http.get<DossierEntry[]>(`${this.baseUrl}/${patientUUID}/DossierEntry/` + entryType);
}

我有一个这样的父组件:

export class DossierCorrespondenceComponent implements OnInit {

  correspondenceEntries$: Observable<DossierEntry[]>;

  @Input() allCorrespondence: Array<DossierEntry>;
  @Input() correspondenceEntries: Array<DossierEntry>;
  @Input() attachmentEntries: Array<DossierEntry>;

  message = '';
  emptyMessageCorrespondentie = 'Geen correspondentie.';
  errorMessageConnection = 'Er ging iets mis met de connectie. Probeer over enkele minuten nogmaals.';

  correspondenceLoaded = false;

  showingSingle = false;

  single: DossierEntry;

  constructor(
    private documentCorrespondeceService: DocumentCorrespondenceService,

    private authService: AuthService  ) {}

  ngOnInit() {

    this.authService.loginStatus().subscribe(user => {
      const UUID = user.profile.participant;

    this.documentCorrespondeceService.getDossierEntry(UUID, 'correspondence').subscribe(result => {
        this.handleCorrespondenceLoad(result), (this.correspondenceLoaded = true);
      }, () => (this.message = this.errorMessageConnection));
    });
  }


   handleCorrespondenceLoad(result: any) {
    if (result.length === 0) {
      this.message = this.emptyMessageCorrespondentie;
      return;
    }
    this.allCorrespondence = result;
    this.attachmentEntries = [];
    this.correspondenceEntries = [];

    const groups = _.groupBy(result, 'type');
    this.correspondenceEntries = groups.correspondence;
    this.attachmentEntries = groups.attachments;
  }
}

html 模板如下所示:

<app-vital10-page [noTopBar]="true">
  <h2 class="dossier-page-header">Correspondentie</h2>

  <p class="data-entry" *ngIf="!allCorrespondence">{{ message }}</p>
  <app-is-loading *ngIf="!correspondenceLoaded" message="Correspondentie wordt geladen"></app-is-loading> 

  <app-dossier-correspondence-list [correspondenceEntries] = "correspondenceEntries$ | async" ></app-dossier-correspondence-list>
  <app-dossier-correspondence-item
    [item]="single"
    (goBack)="goBack($event)"
    *ngIf="showingSingle">
  </app-dossier-correspondence-item>
</app-vital10-page>

然后我有一个像这样的子组件:

export class DossierCorrespondenceListComponent implements OnInit {

  @Input()
  correspondenceEntries: DossierEntry[];

  @Input() showingSingle;

  constructor() { }

  ngOnInit() {
  }

}

模板看起来像这样:


<div *ngIf="!showingSingle  && correspondenceEntries && correspondenceEntries.length > 0;">
  <div class="main-row main-row-dossier">
    <section class="data-entry">
      <h3 class="dossier-header">Algemeen</h3>
      <table class="dossier-table" *ngIf="correspondenceEntries  else loadingCorrespondenceEntires ">
        <thead class="dossier-tableheader">
          <tr>
            <th class="dossier-tablehead fixed-one-fifth">Datum</th>
            <th class="dossier-tablehead fixed-four-fifths">Onderwerp</th>
          </tr>
        </thead>
        <tbody class="dossier-tablebody">
          <tr class="dossier-correspondencerow" *ngFor="let entry of correspondenceEntries; let i = index" (click)="gotoItem(i, entry.type)">
            <td>{{ entry.date | date:"dd-MM-y" }}</td>
            <td>{{ entry.name }}</td>
          </tr>
        </tbody>
      </table>
    </section>
  </div>
</div>

<ng-template #loadingCorrespondenceEntires>
  <div>..Loading </div>
</ng-template>


但是现在子组件的数据在Parent组件中是不可见的。但是加载了正确的数据。因为如果我对此进行 console.log :

 this.correspondenceEntries = groups.correspondence;
    this.attachmentEntries = groups.attachments;

我看到了正确的数组。但不在视图中(htm 文件)

问题在于:

correspondenceEntries$: Observable<DossierEntry[]>;

所以我的问题是,如何通过这个来传递 observable:

 this.authService.loginStatus().subscribe(user => {
      const UUID = user.profile.participant;

    this.documentCorrespondeceService.getDossierEntry(UUID, 'correspondence').subscribe(result => {
        this.handleCorrespondenceLoad(result), (this.correspondenceLoaded = true);
      }, () => (this.message = this.errorMessageConnection));
    });
  }

这样你就不必使用订阅方法了:

.subscribe(result => {
        this.handleCorrespondenceLoad(result), (this.correspondenceLoaded = true);
      }, () => (this.message = this.errorMessageConnection));

你会在视图中看到数据

谢谢。

所以我想这样做:

ngOnInit() {

    this.authService.loginStatus().subscribe(user => {
      const UUID = user.profile.participant;

 this.correspondenceEntries$ =   this.documentCorrespondeceService.getDossierEntry(UUID, 'correspondence').subscribe(result => {
        this.handleCorrespondenceLoad(result), (this.correspondenceLoaded = true);
      }, () => (this.message = this.errorMessageConnection));
    });
  }

但这当然行不通。但是不知道别人怎么做?

所以这是输出:

dossier-corresponden…ist.component.ts:21 
{correspondenceEntries: SimpleChange}
correspondenceEntries: SimpleChange
currentValue: null
firstChange: true
previousValue: undefined

好吧,如果我这样做:

<app-vital10-page [noTopBar]="true">
  <h2 class="dossier-page-header">Correspondentie</h2>

  <p class="data-entry" *ngIf="!allCorrespondence">{{ message }}</p>


<ng-container *ngIf="(correspondenceEntries$ | async) as correspondenceEntries">

  <app-dossier-correspondence-list [correspondenceEntries]="correspondenceEntries" ></app-dossier-correspondence-list>

</ng-container>


  <app-dossier-correspondence-item
    [item]="single"
    (goBack)="goBack($event)"
    *ngIf="showingSingle">
  </app-dossier-correspondence-item>
</app-vital10-page>

那么在视图中仍然没有输出。但我在控制台中得到了这个:

(13) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

但我看到了:

currentValue: null

但如果我这样做:

ngOnInit() {

    console.log(this.correspondenceEntries$);

    this.authService.loginStatus().subscribe(user => {
      const UUID = user.profile.participant;

  this.correspondenceEntries$ =    this.documentCorrespondeceService.getDossierEntry(UUID, 'correspondence')
    });
  }

然后我看到视图中的项目。

但是所以我删除了所有这些:

.subscribe(result => {
        this.handleCorrespondenceLoad(result), (this.correspondenceLoaded = true);
      }, () => (this.message = this.errorMessageConnection));

这样说对吗?

不,这是不正确的。因为现在这将是一个大名单。并且不是两个单独的列表(数组)

【问题讨论】:

  • 为什么不直接在子节点中获取数据,因为您似乎没有在任何地方使用父节点中的数据,所以不是在父节点中获取数据并将其传递给子节点,而是直接在子节点中调用该服务跨度>
  • 你能告诉我怎么做吗?会很好
  • ok,但是孩子只是一个演示视图。我的意思是通过模式智能演示组件。这不是正确的做法。我了解到的是,演示视图不会知道数据来自哪里。还是我错了?
  • 检查“DossierCorrespondenceListComponent”中的更改,以确保您收到预期的数据。如果是,可能是某些模板逻辑和/或样式阻碍了数据的可见性。
  • 回答您使用 Observable 而不手动订阅的问题是使用异步管道,就像您在 DossierCorrespondenceComponent 的模板中获取“correspondenceEntries$”一样。使用这种方法可以自动订阅和取消订阅。

标签: javascript angular typescript rxjs observable


【解决方案1】:

我认为您正在寻找的是 *ngIf 指令中的 as 关键字,您可以按如下方式使用:

...
<ng-container *ngIf="(correspondenceEntries$ | async) as correspondenceEntries">
  ...
  <app-dossier-correspondence-list [correspondenceEntries]="correspondenceEntries" ></app-dossier-correspondence-list>
  ...
</ng-container>
...

as 关键字将其前面的值(在本例中为 Observable 发出并由异步管道提取的值)存储在其后面的变量中。不幸的是the as keyword is currently (i.e. Angular 8) only available within the *ngIf directive,所以你必须使用*ngIf,即使你不需要它的条件模板渲染方面。

StackBlitz Example

【讨论】:

  • 我尝试了你的建议。但我在视图中看不到任何东西。这很奇怪。因为数据已加载。我在控制台中看到它。但不在视图中。
  • 我不确定问题出在您的应用程序中。我在对 StackBlitz 示例的回答中添加了一个链接,希望能帮助您找到问题。
  • 我发布了解决方案。
【解决方案2】:

好的,我是这样解决的:

<ng-container *ngIf="correspondenceEntries">
    <app-dossier-correspondence-list [correspondenceEntries]="correspondenceEntries"> </app-dossier-correspondence-list>
  </ng-container>

  <ng-container *ngIf="attachmentEntries">
    <app-dossier-correspondence-attachments
      [attachmentEntries]="attachmentEntries"
    ></app-dossier-correspondence-attachments>
  </ng-container>

谢谢大家的努力

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多