Estoy tratando de entender cómo usar Observables en Angular 2. Tengo este servicio:
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));
}
}
A este BehaviorSubject se le envían nuevos valores desde otro servicio:
that._appointmentChoiceStore._appointmentChoices.next(parseObject)
Me suscribo a él en forma de observable en el componente en el que quiero mostrarlo:
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
})
}
}
Y el intento de mostrar en la vista así:
<li *ngFor="#appointment of _nextFourAppointments.availabilities | async">
<div class="text-left appointment-flex">{{appointment | date: 'EEE' | uppercase}}
Sin embargo, la disponibilidad aún no es una propiedad del objeto observable, por lo que se produce un error, incluso aunque lo defina en la interfaz de disponibilidades de la siguiente manera:
export interface Availabilities {
"availabilities": string[],
"length": number
}
¿Cómo puedo mostrar una matriz de forma asíncrona desde un objeto observable con la tubería asíncrona y * ngFor? El mensaje de error que recibo es:
browser_adapter.js:77 ORIGINAL EXCEPTION: TypeError: Cannot read property 'availabilties' of undefined
typescript
angular
rxjs
observable
C. Kearns
fuente
fuente
*ngFor="let appointment of _nextFourAppointments.availabilities | async">
availabilties
mientras debería haberavailabilities
Respuestas:
Aquí hay un ejemplo
// 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>
fuente
public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).subscribe() }
, mi función get está devolviendo un sujeto:, en el controlador cuando lo configuro igual, obtengo el error:,browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe'
¿cómo convierto el sujeto en un observable?public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities).asObservable()) } }
esto me da el error:,property asObservable does not exist on type observable
pero _appointmentChoices es unSubject
?Quien alguna vez también se tropiece con esta publicación.
Creo que es la forma correcta:
<div *ngFor="let appointment of (_nextFourAppointments | async).availabilities;"> <div>{{ appointment }}</div> </div>
fuente
Creo que lo que buscas es esto
<article *ngFor="let news of (news$ | async)?.articles"> <h4 class="head">{{news.title}}</h4> <div class="desc"> {{news.description}}</div> <footer> {{news.author}} </footer>
fuente
Si no tiene una matriz pero está tratando de usar su observable como una matriz, aunque sea una secuencia de objetos, esto no funcionará de forma nativa. A continuación, muestro cómo solucionar este problema, asumiendo que solo le importa agregar objetos al observable, no eliminarlos.
Si está tratando de usar un observable cuya fuente es de tipo BehaviorSubject, cámbielo a ReplaySubject y luego en su componente suscríbase a él de esta manera:
Componente
this.messages$ = this.chatService.messages$.pipe(scan((acc, val) => [...acc, val], []));
HTML
<div class="message-list" *ngFor="let item of messages$ | async">
fuente
scan
operador puede utilizar.pipe(toArray())
Subject
es no llamarcomplete()
. El acumulador nunca funcionará.