问题
I'm playing with angular2 alpha 40 with ng2-play starter from pawel. Examples are in typescript.
I have a service MovieList like this:
export class Movie {
selected: boolean = false
constructor(public name:string, public year:number, public score:number) {}
}
export class MovieListService {
list: Array<Movie>
selectMovie = new EventEmitter();
constructor() {
this.list = [new Movie('Star Wars', 1977, 4.4)];
}
add(m:Movie) {
this.list.push(m);
}
remove(m:Movie) {
for(var i = this.list.length - 1; i >= 0; i--) {
if(this.list[i] === m) {
if(m.selected) this.selectMovie.next();
this.list.splice(i, 1);
}
}
}
select(m:Movie) {
this.list.map((m) => m.selected = false);
m.selected = true;
this.selectMovie.next(m);
}
}
I have a component showing the movies list and make possible to select one by clicking on it, which call select() in the service above.
And I have another component (on the same level, I don't want to use (selectmovie)="select($event)") which subscribe to the movie selection event like this:
@Component({
selector: 'movie-edit',
})
@View({
directives: [NgIf],
template: `
<div class="bloc">
<p *ng-if="currentMovie == null">No movie selected</p>
<p *ng-if="currentMovie != null">Movie edition in progress !</p>
</div>
`
})
export class MovieEditComponent {
currentMovie:Movie
constructor(public movieList: MovieListService) {
this.movieList.selectMovie.toRx().subscribe(this.movieChanged);
setTimeout(() => { this.movieChanged('foo'); }, 4000);
}
movieChanged(f:Movie = null) {
this.currentMovie = f;
console.log(this.currentMovie);
}
}
The event is subscribed using .toRx().subscribe() on the eventEmitter.
movieChanged() is called but nothing happen in the template..
I tried using a timeout() calling the same function and changes are refleted in the template.
回答1:
The problem seems to be the fact that subscribe expects an Observer or three functions that work as an observer while you are passing a normal function. So in your code I just changed movieChanged to be an Observer instead of a callback function.
movieChanged: Observer = Observer.create(
(f) => { this.currentMovie = f; }, // onNext
(err) => {}, // onError
() => {} // onCompleted
);
See this plnkr for an example. It would have been nice to see a minimal working example of your requirement so my solution would be closer to what you are looking for. But if I understood correctly this should work for you. Instead of a select I just used a button to trigger the change.
Update
You can avoid creating the Òbserver just by passing a function to the subscriber method (clearly there's a difference between passing directly a function and using a class method, don't know really why is different)
this.movieList.selectMovie.toRx().subscribe((m: Movie = null) => {
this.currentMovie = m;
});
Note
EventEmitter is being refactored, so in future releases next will be renamed to emit.
Note 2
Angular2 moved to @reactivex/rxjs but in the plnkr I'm not able to use directly those libs (didn't find any cdn). But you can try in your own project using these libs.
I hope it helps.
回答2:
The movieChanged function expects the movie object and not the String. Try changing below code
setTimeout(() => { this.movieChanged('foo'); }, 4000);
to
setTimeout(() => { this.movieChanged(new Movie('Troy', 2000 , 8)); }, 4000);
来源:https://stackoverflow.com/questions/33063434/this-myservice-myevent-torx-subscribe-called-but-no-dom-refresh-zone-trigge