Menggunakan array dari Objek Observable dengan ngFor dan Async Pipe Angular 2

93

Saya mencoba untuk memahami bagaimana menggunakan Observables di Angular 2. Saya memiliki layanan ini:

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

BehaviorSubject ini didorong oleh nilai-nilai baru dari layanan lain:

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

Saya berlangganan dalam bentuk yang dapat diamati di komponen yang ingin saya tampilkan di:

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

Dan upaya untuk menampilkan dalam tampilan sebagai:

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

Namun, ketersediaan belum menjadi properti dari objek yang dapat diamati sehingga terjadi kesalahan, bahkan saya pikir saya mendefinisikannya di antarmuka ketersediaan sebagai:

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

Bagaimana cara menampilkan array secara asinkron dari objek yang dapat diamati dengan pipa asinkron dan * ngFor? Pesan kesalahan yang saya dapatkan adalah:

browser_adapter.js:77 ORIGINAL EXCEPTION: TypeError: Cannot read property 'availabilties' of undefined
C. Kearns
sumber
Apa pesan kesalahan yang sebenarnya?
Günter Zöchbauer
diedit untuk menambah kesalahan
C. Kearns
dengan angular-rc1 terbaru sintaksnya adalah*ngFor="let appointment of _nextFourAppointments.availabilities | async">
Jagannath
ini benar, tetapi tidak menyebabkan kesalahan. itu hanya memberi peringatan.
C. Kearns
3
Saya yakin ada kesalahan ketik di suatu tempat. Kesalahan mengatakan availabiltiessementara seharusnya adaavailabilities
Ivan Sivak

Jawaban:

154

Berikut contohnya

// 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>
Relu Mesaros
sumber
fungsi get saya mengembalikan subjek:, public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() } di pengontrol ketika saya menyetelnya sama, saya mendapatkan kesalahan:, browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe'bagaimana cara mengubah subjek menjadi yang dapat diamati?
C. Kearns
public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } } ini memberi saya kesalahan property asObservable does not exist on type observable:, tetapi _appointmentChoices adalah Subject?
C. Kearns
Itu sudah bisa diamati! Saya hanya perlu berlangganan!
C. Kearns
Saya memiliki masalah tambahan dengan mengintegrasikan mata pelajaran. Berikut adalah StackBlitz menggunakan observable dan subjek: stackblitz.com/edit/subject-as-observable-list-example
IceWarrior353
12

Siapa yang juga tersandung posting ini.

Saya percaya adalah cara yang benar:

  <div *ngFor="let appointment of (_nextFourAppointments | async).availabilities;"> 
    <div>{{ appointment }}</div>
  </div>
Martin Søberg
sumber
1

Saya pikir apa yang Anda cari adalah ini

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

Nixon Mathew
sumber
1

Jika Anda tidak memiliki array tetapi Anda mencoba menggunakan observable Anda seperti array meskipun itu adalah aliran objek, ini tidak akan berfungsi secara native. Saya menunjukkan cara memperbaikinya di bawah ini dengan asumsi Anda hanya peduli tentang menambahkan objek ke yang dapat diamati, bukan menghapusnya.

Jika Anda mencoba menggunakan observable yang sumbernya berjenis BehaviorSubject, ubah ke ReplaySubject lalu di komponen Anda berlangganan seperti ini:

Komponen

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

Html

<div class="message-list" *ngFor="let item of messages$ | async">
Posting Impatica
sumber
Alih-alih scanoperator, Anda dapat menggunakan.pipe(toArray())
MotKohn
Perangkap lain saat membuat sendiri Subjectadalah tidak menelepon complete(). Akumulator tidak akan pernah bekerja.
MotKohn