I am facing an issue with the Angular2 router and an async pipe.
I am trying to render an RxJs Observable and the data does not render automatically.
One has to click on the link for the route for the data to render.
Here is the root app:
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {AppComponent} from './app.component.ts';
bootstrap(AppComponent, [HTTP_PROVIDERS, ROUTER_PROVIDERS]);
Here is the root component:
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {FirstComponent} from './app.first-component.ts';
import {SecondComponent} from './app.second-component.ts';
import {AppService} from "./app.services.ts";
@Component({
selector: 'my-app',
providers: [AppService, FirstComponent, SecondComponent],
directives: [FirstComponent, SecondComponent, ROUTER_DIRECTIVES],
template: `<h1>An Angular 2 App</h1>
<a [routerLink]="['First']">first-default</a>
<a [routerLink]="['Second']">second</a>
<router-outlet></router-outlet>`
})
@RouteConfig([
{path: '/', name: 'First', component: FirstComponent, useAsDefault: true},
{path: '/second', name: 'Second', component: SecondComponent}
])
export class AppComponent {
}
Here is First component:
import {Component} from "angular2/core";
import {AppService} from "./app.services.ts";
import "rxjs/Rx";
@Component({
selector: 'my-first',
template: `
<div>
<ul>
<li *ngFor="#s of appService.someObservable$ | async">
a string: {{ s }}
</li>
</ul>
</div>`
})
export class FirstComponent {
constructor(private appService:AppService) {
console.log('constructor', 'first');
}
}
and finally the service (where the data resides):
import {Injectable} from "angular2/core";
import {Observable} from "rxjs/Rx";
@Injectable()
export class AppService {
constructor() {
console.log('constructor', 'appService');
this.constructSomeObservable();
}
someObservable$:Observable <string[]>;
constructSomeObservable() {
this.someObservable$ = Observable.create(observer => {
const eventSource = new EventSource('/interval-sse-observable');
eventSource.onmessage = x => observer.next(JSON.parse(x.data));
eventSource.onerror = x => observer.error(console.log('EventSource failed'));
return () => {
eventSource.close();
};
})
.startWith([])
.scan((acc, value) => acc.concat(value));
}
}
What I am getting wrong with the router or the pipe?
See sample project on github here.
edit: Here is the modified version of the component:
import {Component} from "angular2/core";
import {AppService} from "./app.services.ts";
import {Observable} from "rxjs/Rx";
@Component({
selector: 'my-first',
template: `
<div>
<ul>
<li *ngFor="#s of someObservable$ | async">
a string: {{ s }}
</li>
</ul>
</div>`
})
export class FirstComponent {
someObservable$:Observable <string[]>;
constructor(private appService:AppService) {
console.log('constructor', 'first');
this.someObservable$ = appService.someObservable$;
}
}
The data is not updated in the template. Is it to do with two/one way binding?
See Question&Answers more detail:
os