ChatGPT解决这个技术问题 Extra ChatGPT

Using an array from Observable Object with ngFor and Async Pipe Angular 2

I am trying to understand how to use Observables in Angular 2. I have this 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));
    }
}

This BehaviorSubject is pushed new values as so from another service:

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

I subscribe to it in the form of an observable in the component I want to display it in:

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

And the attempt to display in the view as so:

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

However, availabilities isn't yet a property of the observable object so it errors out, even though I define it in the availabilities interface as so:

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

How can I display an array asynchronously from an observable object with the async pipe and *ngFor? The error message I get is:

browser_adapter.js:77 ORIGINAL EXCEPTION: TypeError: Cannot read property 'availabilties' of undefined
What's the actual error message?
edited to add error
with the latest angular-rc1 the syntax is *ngFor="let appointment of _nextFourAppointments.availabilities | async">
this is true, but it is not causing the error. it simply throws a warning.
I believe there is a typo somewhere. The error says availabilties while there should be availabilities

R
Relu Mesaros

Here's an example

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

my get function is returning a subject though: public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() } , in the controller when I set it equal, I get the error: browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe', how do I turn the subject into an observable?
public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } } this gives me the error: property asObservable does not exist on type observable, but _appointmentChoices is a Subject?
It already was an observable! I just needed to subscribe to it!
I had an additional problem with integrating subjects. Here's a StackBlitz using observables and subjects: stackblitz.com/edit/subject-as-observable-list-example
M
Martin Søberg

Who ever also stumbles over this post.

I belive is the correct way:

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

N
Nixon Mathew

I think what u r looking for is this

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


P
Post Impatica

If you don't have an array but you are trying to use your observable like an array even though it's a stream of objects, this won't work natively. I show how to fix this below assuming you only care about adding objects to the observable, not deleting them.

If you are trying to use an observable whose source is of type BehaviorSubject, change it to ReplaySubject then in your component subscribe to it like this:

Component

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

Html

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

Instead of the scan operator you can use .pipe(toArray())
Another pitfall when creating your own Subject is not calling complete(). The accumulator will never run.

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now