In my Angular6 application I have a problem with displaying data with async ngfor. I am expecting some Server Sent Events from backend (just object with answer string field). While console.log shows that answer list from service contains answers, ngfor displays nothing.
Here is my component:
import { Component } from '@angular/core';
import { Answer } from './answer';
import { AnswerReactiveService } from './answer-reactive.service';
import { Observable } from 'rxjs';
@Component({
selector: 'app-answers',
templateUrl: './answers.component.html',
providers: [AnswerReactiveService],
styleUrls: ['./answers.component.css']
})
export class AnswersComponent {
answers: Observable<Answer[]>;
constructor(private answerReactiveService: AnswerReactiveService) {
}
requestAnswerStream(): void {
this.answers = this.answerReactiveService.getAnswerStream();
}
}
Here is the service:
import { Injectable } from '@angular/core';
import { Answer } from './answer';
import { Observable } from 'rxjs';
@Injectable()
export class AnswerReactiveService {
private answers: Answer[] = [];
private url: string = 'http://localhost:8080/events/1';
getAnswerStream(): Observable<Array<Answer>> {
return Observable.create((observer) => {
let url = this.url;
let eventSource = new EventSource(url);
eventSource.onmessage = (event) => {
console.log('Received event: ', event);
const json = JSON.parse(event.data);
console.log(json);
this.answers.push(new Answer(json['answer']));
console.log(this.answers);
observer.next(this.answers);
};
eventSource.onerror = (error) => {
if (eventSource.readyState === 0) {
console.log('The stream has been closed by the server.');
eventSource.close();
observer.complete();
} else {
observer.error('EventSource error: ' + error);
}
};
});
}
}
And HTML:
<div class="row">
<div class="col-md-8">
<p>
<button (click)="requestAnswerStream()">Gimmie answers</button>
</p>
<ul>
<li *ngFor="let answer of answers | async">{{answer.answer}}</li>
</ul>
</div>
</div>
Once you got the service result complete the sequence by using observer.complete after emit the value using observer.next()
Inside component
And then in Html you can simply iterate the answers