Sử dụng một mảng từ Đối tượng có thể quan sát với ngFor và Async Pipe Angular 2


91

Tôi đang cố gắng hiểu cách sử dụng Observables trong Angular 2. Tôi có dịch vụ này:

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 này được đẩy các giá trị mới từ một dịch vụ khác:

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

Tôi đăng ký nó dưới dạng một thành phần có thể quan sát được trong thành phần mà tôi muốn hiển thị nó trong:

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

Và cố gắng hiển thị trong chế độ xem như vậy:

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

Tuy nhiên, tính khả dụng vẫn chưa phải là thuộc tính của đối tượng có thể quan sát nên nó bị lỗi, thậm chí tôi nghĩ rằng tôi định nghĩa nó trong giao diện tình trạng sẵn có như vậy:

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

Làm cách nào để hiển thị một mảng không đồng bộ từ một đối tượng có thể quan sát được với đường ống không đồng bộ và * ngFor? Thông báo lỗi tôi nhận được là:

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

Thông báo lỗi thực sự là gì?
Günter Zöchbauer

chỉnh sửa để thêm lỗi
C. Kearns

với góc-rc1 mới nhất của cú pháp là*ngFor="let appointment of _nextFourAppointments.availabilities | async">
Jagannath

điều này đúng, nhưng nó không gây ra lỗi. nó chỉ đơn giản là ném một cảnh báo.
C. Kearns

3
Tôi tin rằng có một lỗi đánh máy ở đâu đó. Lỗi nói availabiltieskhi cần cóavailabilities
Ivan Sivak

Câu trả lời:


152

Đây là một ví dụ

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

Mặc dù vậy public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() } , hàm get của tôi đang trả về một chủ đề : , trong bộ điều khiển khi tôi đặt nó bằng nhau, tôi gặp lỗi : browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe', làm cách nào để chuyển chủ thể thành có thể quan sát được?
C. Kearns

public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } } điều này mang lại cho tôi lỗi property asObservable does not exist on type observable:, nhưng _appointmentChoices là Subject?
C. Kearns

Nó đã là một quan sát được! Tôi chỉ cần đăng ký vào nó!
C. Kearns

Tôi đã có thêm một vấn đề với việc tích hợp các môn học. Dưới đây là một StackBlitz sử dụng quan sát và đối tượng: stackblitz.com/edit/subject-as-observable-list-example
IceWarrior353

11

Ai cũng từng vấp phải bài viết này.

Tôi tin rằng đó là cách chính xác:

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

1

Tôi nghĩ thứ bạn đang tìm là cái này

<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

Nếu bạn không có một mảng nhưng bạn đang cố gắng sử dụng mảng có thể quan sát được của mình như một mảng mặc dù đó là một luồng đối tượng, điều này sẽ không hoạt động nguyên bản. Tôi chỉ cách khắc phục điều này dưới đây giả sử bạn chỉ quan tâm đến việc thêm các đối tượng vào có thể quan sát được chứ không phải xóa chúng.

Nếu bạn đang cố gắng sử dụng một đối tượng có thể quan sát có nguồn thuộc loại BehaviorSubject, hãy thay đổi nó thành ReplaySubject sau đó trong thành phần của bạn đăng ký nó như thế này:

Thành phần

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

Html

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

Thay vì scantoán tử, bạn có thể sử dụng.pipe(toArray())
MotKohn

Một cạm bẫy khác khi tạo của riêng bạn Subject là không gọi được complete(). Bộ tích lũy sẽ không bao giờ chạy.
MotKohn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.