109 votes

Utiliser un tableau à partir d'un objet Observable avec ngFor et Async Pipe Angular 2

J'essaie de comprendre comment utiliser les Observables dans Angular 2. J'ai ce 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));
    }
}

Ce BehaviorSubject est poussé de nouvelles valeurs ainsi d'un autre service :

that._appointmentChoiceStore._appointmentChoices.next(parseObject)

Je m'y abonne sous la forme d'un observable dans le composant dans lequel je veux l'afficher :

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

Et la tentative d'affichage dans la vue comme tel :

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

Cependant, availabilities n'est pas encore une propriété de l'objet observable, ce qui entraîne une erreur, même si je la définis comme telle dans l'interface availabilities :

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

Comment puis-je afficher un tableau de manière asynchrone à partir d'un objet observable avec le tube asynchrone et *ngFor ? Le message d'erreur que j'obtiens est le suivant :

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

0 votes

Quel est le message d'erreur réel ?

0 votes

Modifié pour ajouter l'erreur

0 votes

Avec la dernière version d'angular-rc1, la syntaxe est la suivante *ngFor="let appointment of _nextFourAppointments.availabilities | async">

165voto

Relu Mesaros Points 4632

Voici un exemple

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

0 votes

Ma fonction get renvoie un sujet cependant : public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return this._appointmentChoices.map(object=>object.availabilities).‌​subscribe() } Dans le contrôleur, lorsque je l'égalise, j'obtiens l'erreur suivante : browser_adapter.js:77Error: Invalid argument '[object Object]' for pipe 'AsyncPipe' comment transformer le sujet en observable ?

0 votes

public _appointmentChoices: Subject<any> = new Subject() getAppointments() { return (this._appointmentChoices.map(object=>object.availabilities)‌​.asObservable()) } } cela me donne l'erreur : property asObservable does not exist on type observable mais _appointmentChoices est un outil de gestion de l'information. Subject ?

0 votes

C'était déjà un observable ! J'avais juste besoin de m'y abonner !

20voto

Martin Søberg Points 391

Qui que ce soit qui tombe aussi sur ce post.

Je crois que c'est la bonne méthode :

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

2voto

Nixon Mathew Points 61

Je pense que ce que tu cherches est ceci

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

1voto

Helzgate Points 11

Si vous n'avez pas de tableau mais que vous essayez d'utiliser votre observable comme un tableau alors qu'il s'agit d'un flux d'objets, cela ne fonctionnera pas en mode natif. Je montre comment résoudre ce problème ci-dessous en supposant que vous ne vous souciez que d'ajouter des objets à l'observable, et non de les supprimer.

Si vous essayez d'utiliser un observable dont la source est de type BehaviorSubject, changez-le en ReplaySubject puis, dans votre composant, abonnez-vous à cet observable de la manière suivante :

Composant

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

Html

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X