Verwenden eines Arrays aus Observable Object mit ngFor und Async Pipe Angular 2


91

Ich versuche zu verstehen, wie Observables in Angular 2 verwendet werden. Ich habe diesen Service:

import {Injectable, EventEmitter, ViewChild} from '@angular/core';
import {Observable} from "rxjs/Observable";
import {Subject} from "rxjs/Subject";
import {BehaviorSubject} from "rxjs/Rx";
import {Availabilities} from './availabilities-interface'

@Injectable()
export class AppointmentChoiceStore {
    public _appointmentChoices: BehaviorSubject<Availabilities> = new BehaviorSubject<Availabilities>({"availabilities": [''], "length": 0})

    constructor() {}

    getAppointments() {
        return this.asObservable(this._appointmentChoices)
    }
    asObservable(subject: Subject<any>) {
        return new Observable(fn => subject.subscribe(fn));
    }
}

Diesem BehaviorSubject werden neue Werte von einem anderen Dienst übertragen:

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

Ich abonniere es in Form eines Observable in der Komponente, in der ich es anzeigen möchte:

import {Component, OnInit, AfterViewInit} from '@angular/core'
import {AppointmentChoiceStore} from '../shared/appointment-choice-service'
import {Observable} from 'rxjs/Observable'
import {Subject} from 'rxjs/Subject'
import {BehaviorSubject} from "rxjs/Rx";
import {Availabilities} from '../shared/availabilities-interface'


declare const moment: any

@Component({
    selector: 'my-appointment-choice',
    template: require('./appointmentchoice-template.html'),
    styles: [require('./appointmentchoice-style.css')],
    pipes: [CustomPipe]
})

export class AppointmentChoiceComponent implements OnInit, AfterViewInit {
    private _nextFourAppointments: Observable<string[]>

    constructor(private _appointmentChoiceStore: AppointmentChoiceStore) {
        this._appointmentChoiceStore.getAppointments().subscribe(function(value) {
            this._nextFourAppointments = value
        })
    }
}

Und der Versuch, in der Ansicht so anzuzeigen:

  <li *ngFor="#appointment of _nextFourAppointments.availabilities | async">
         <div class="text-left appointment-flex">{{appointment | date: 'EEE' | uppercase}}

Die Verfügbarkeit ist jedoch noch keine Eigenschaft des beobachtbaren Objekts, sodass es zu Fehlern kommt, obwohl ich es in der Verfügbarkeitsschnittstelle wie folgt definiert habe:

export interface Availabilities {
  "availabilities": string[],
  "length": number
}

Wie kann ich ein Array von einem beobachtbaren Objekt mit der asynchronen Pipe und * ngFor asynchron anzeigen? Die Fehlermeldung, die ich erhalte, lautet:

browser_adapter.js:77 ORIGINAL EXCEPTION: TypeError: Cannot read property 'availabilties' of undefined

Was ist die eigentliche Fehlermeldung?
Günter Zöchbauer

bearbeitet, um Fehler hinzuzufügen
C. Kearns

mit dem neuesten angle-rc1 lautet die Syntax*ngFor="let appointment of _nextFourAppointments.availabilities | async">
Jagannath

Dies ist wahr, verursacht aber keinen Fehler. es gibt einfach eine Warnung aus.
C. Kearns

3
Ich glaube, irgendwo gibt es einen Tippfehler. Der Fehler sagt, availabiltiessolange es sein sollteavailabilities
Ivan Sivak

Antworten:


152

Hier ist ein Beispiel

// in the service
getVehicles(){
    return Observable.interval(2200).map(i=> [{name: 'car 1'},{name: 'car 2'}])
}

// in the controller
vehicles: Observable<Array<any>>
ngOnInit() {
    this.vehicles = this._vehicleService.getVehicles();
}

// in template
<div *ngFor='let vehicle of vehicles | async'>
    {{vehicle.name}}
</div>

Meine Get-Funktion gibt jedoch ein Motiv zurück: public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() } Wenn ich es in der Steuerung gleich setze, wird der Fehler angezeigt: browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe'Wie verwandle ich das Motiv in ein Observable?
C. Kearns

public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } } das gibt mir den property asObservable does not exist on type observablefehler : , aber _appointmentChoices ist ein Subject?
C. Kearns

Es war schon ein beobachtbarer! Ich musste es nur abonnieren!
C. Kearns

Ich hatte ein zusätzliches Problem mit der Integration von Themen. Hier ist ein StackBlitz mit Observablen und Subjekten: stackblitz.com/edit/subject-as-observable-list-example
IceWarrior353

11

Wer stolpert auch über diesen Beitrag.

Ich glaube, das ist der richtige Weg:

  <div *ngFor="let appointment of (_nextFourAppointments | async).availabilities;"> 
    <div>{{ appointment }}</div>
  </div>

1

Ich denke, was du suchst, ist das hier

<article *ngFor="let news of (news$ | async)?.articles">
<h4 class="head">{{news.title}}</h4>
<div class="desc"> {{news.description}}</div>
<footer>
    {{news.author}}
</footer>


1

Wenn Sie kein Array haben, aber versuchen, Ihr Observable wie ein Array zu verwenden, obwohl es sich um einen Objektstrom handelt, funktioniert dies nicht nativ. Im Folgenden wird gezeigt, wie Sie dieses Problem beheben können, vorausgesetzt, Sie möchten dem Observable nur Objekte hinzufügen und nicht löschen.

Wenn Sie versuchen, ein Observable zu verwenden, dessen Quelle vom Typ BehaviorSubject ist, ändern Sie es in ReplaySubject und abonnieren Sie es in Ihrer Komponente wie folgt:

Komponente

this.messages$ = this.chatService.messages$.pipe(scan((acc, val) => [...acc, val], []));

Html

<div class="message-list" *ngFor="let item of messages$ | async">

Anstelle des scanOperators können Sie.pipe(toArray())
MotKohn

Eine weitere Gefahr beim Erstellen Ihrer eigenen Subjectist das Nicht-Anrufen complete(). Der Akku wird niemals laufen.
MotKohn
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.