Używanie tablicy z obiektu obserwowalnego z ngFor i Async Pipe Angular 2


93

Próbuję zrozumieć, jak używać Observables w Angular 2. Mam tę usługę:

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));
    }
}

To BehaviorSubject jest wypychane nowe wartości z innej usługi:

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

Subskrybuję go w postaci obserwowalnego w komponencie, w którym chcę go wyświetlić:

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
        })
    }
}

I próba wyświetlenia w widoku tak:

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

Jednak dostępność nie jest jeszcze właściwością obserwowalnego obiektu, więc popełnia błędy, nawet myślałem, że zdefiniowałem to w interfejsie dostępności tak:

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

Jak mogę wyświetlić tablicę asynchronicznie z obserwowalnego obiektu za pomocą potoku asynchronicznego i * ngFor? Otrzymuję komunikat o błędzie:

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

Jaki jest rzeczywisty komunikat o błędzie?
Günter Zöchbauer

edytowane w celu dodania błędu
C.Kearns

z najnowszym angular-rc1 składnia to*ngFor="let appointment of _nextFourAppointments.availabilities | async">
Jagannath

to prawda, ale nie powoduje błędu. po prostu rzuca ostrzeżenie.
C. Kearns

3
Myślę, że gdzieś jest literówka. Błąd mówi availabilties, że powinno byćavailabilities
Ivan Sivak

Odpowiedzi:


154

Oto przykład

// 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>

moja funkcja get zwraca jednak temat: public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() } w kontrolerze, gdy ustawię go na równą, pojawia się błąd: browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe'jak zmienić temat w obserwowalny?
C. Kearns,

public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } } to daje mi błąd: property asObservable does not exist on type observableale _appointmentChoices to Subject?
C. Kearns

To już było widoczne! Po prostu musiałem to zasubskrybować!
C. Kearns

Miałem dodatkowy problem z integracją przedmiotów. Oto StackBlitz wykorzystujący obserwowalne i tematy: stackblitz.com/edit/subject-as-observable-list-example
IceWarrior353

12

Kto kiedykolwiek potyka się o ten post.

Wierzę, że to właściwy sposób:

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

1

Myślę, że szukasz tego

<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

Jeśli nie masz tablicy, ale próbujesz użyć tego, co jest obserwowalne, jak tablicy, nawet jeśli jest to strumień obiektów, nie zadziała to natywnie. Poniżej pokazuję, jak to naprawić, zakładając, że zależy Ci tylko na dodawaniu obiektów do obserwowalnych, a nie na ich usuwaniu.

Jeśli próbujesz użyć obserwowalnego, którego źródło jest typu BehaviorSubject, zmień je na ReplaySubject, a następnie w swoim komponencie zasubskrybuj go w następujący sposób:

Składnik

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

HTML

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

Zamiast scanoperatora możesz użyć.pipe(toArray())
MotKohn

Inną pułapką podczas tworzenia własnego Subjectjest brak dzwonienia complete(). Akumulator nigdy nie działa.
MotKohn
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.