2016-07-19 6 views
2

e (1): Aktualisierter Code zur Adressierung von Tippfehlern in der Originalfrage.
e (2): Versuch 'JSON.stringify()' die Daten in 'createContent()' in mein JSON-Objekt zu schieben. Kein Glück.
e (3): plnkr Hinzugefügt wie gewünscht: http://plnkr.co/edit/j024MYCQbypAGaf762fTAsync-Pipe kann Observable nicht rendern

ich ein Modell haben ...

class Content { 
    constructor(public name: string) { } 
} 

Ich habe einen Service ...

class ContentService { 
    private _contents$: Subject<Content[]> 
    = new Subject<Content[]>(); 

    get contents$(): Observable<Content[]> { 
    return this._contents$.asObservable(); 
    } 

    private _data: { contents: Content[] } = { contents: [] }; 

... 

    load(): void { 
    createContent(new Content("Test Content...")); 
    } 

    createContent(item: Content): void { 
    this._data.contents.push(item); 
    this._contents$.next(this._data.contents); 
    } 
} 

ich habe Komponente ...

@Component({ 
... 
template: ` 
<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1> 
` 
}) 
class ContentListComponent { 
    contents$: Observable<Content[]>; 

    constructor(private _contentService: ContentService) { } 

    ngOnInit(): void { 
    this.contents$ = this._contentService.contents$; 
    this._contentService.load(); 
    } 
} 

Einfach gesagt verstehe ich nicht, warum das Observable in meiner Komponente nicht richtig funktioniert.

Wenn ich diese ändern, so dass ich ein Array in der Komponente habe, abonnieren Sie den Service "Inhalt $", um das Array zu füllen, dann ist es kein großes Problem.

Wenn ich die Ausgabe des Dienstes und Funktionen genannt, protokolliert, ist alles auch Dandy. Das einzige Symptom, das ich erfahre, ist, dass der "* ngFor" den Stream nicht richtig zu behandeln scheint. Es ist etwas offensichtlich, oder?

+0

Ich denke, das ist das Problem: 'this.contents $ = this._contentService.contents $;'. Bitte versuchen Sie dies in Ihrer Vorlage: '* ngFor =" let item of _contentService.contents $ | async "' – rinukkusu

+0

Können Sie bitte versuchen, diese Zeile 'this.contents $ = this._contentService.contents $;' in den Contructor zu verschieben? Ich habe es nicht ausprobiert, aber vielleicht gefällt es der Ansicht nicht, wenn 'contents $' 'null' ist, wenn es zuerst versucht, die Bindungen aufzulösen. –

+0

@rinukkusu: Das Backing-Objekt der Komponente hat auch eine Eigenschaft namens 'contents $'. Das war mein Fehler, diese für diese Frage ähnlich zu benennen.Ich habe es jedoch versucht, den Service direkt zu beschaffen. Nichts, leider. –

Antwort

1

Das Problem ist, dass Angular die

<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1> 

nur ausgewertet, wenn Change Detection wird das nächste Mal ausgeführt.

Da

this._service.load(); 

Sync ausgeführt wird, wird das Ereignis ausgesendet, bevor Angular eine Chance hatte, zu abonnieren.

Wenn Sie zum Beispiel einen BehaviorSubject anstelle von Subject verwenden, der den zuletzt ausgegebenen Wert an neue Abonnenten sendet, dann erhalten Sie das gewünschte Verhalten.

Plunker example

Sie können auch manuell vor this._service.load(); Aufruf Änderungserkennung aufrufen oder rufen this._service.load(); verzögert
aber das hängt von Ihren spezifischen Anforderungen.

+1

Super! Danke dafür - ich hatte keine Ahnung, warum BehaviorSubject bis jetzt so wichtig war; nur dass ich das Gefühl hatte, es sei ein Thema von heiß gegen kalt. Danke noch einmal! –

0

Ich sehe ein mögliches Problem in Ihrem Code:

createContent(item: Content): void { 
    this._data.contents$.push(item); 
    this._contents$.next(this._data.contents$); 
} 

ich folgendes stattdessen verwenden würde:

createContent(item: Content): void { 
    this._data.contents.push(item); // <---- 
    this._contents$.next(this._data.contents); // <---- 
} 
+0

Zu viele "Inhalte/$", heh. Entschuldigung, das war nur ein Tippfehler in der ursprünglichen Frage. Ich habe es aktualisiert, um den Code wiederzugeben, den ich habe. –