zpul zpul - 1 year ago 44
TypeScript Question

Service providing a Subject observable doesn't receive notifications

EventSpinner component subscribes to icons provided by EventsService.

@Component({
selector: 'event-spinner',
template: `
<div class="col-xs-5">
Test <i class="fa fa-2x" [ngClass]="{'fa-check': icon == 'ok', 'fa-spin': icon == 'loading', 'fa-spinner': icon == 'loading', 'fa-times': icon == 'error'}" id="spin"></i>
</div>
`
})
export class EventSpinner implements OnInit {
icon: string;

constructor(public eventsService: EventsService) {
}

ngOnInit(): void {
this.eventsService.icons.subscribe((icon) => {
let old = this.icon;
this.icon = icon;
console.log("this.icon = " + this.icon + " (was " + old + ")");
});
}

}


icons.next is called when a web service request using @angular/http.get state changes ("loading"/"ok"/"error"). however when this happens the class of the i tag doesn't get updated. any idea?

EventsService.ts

@Injectable()
export class EventsService {
icons: Subject<string> = new Subject<string>();

constructor(public http: Http) {
}

subscribe(): Observable<Event[]> {
let url = (<any>window).__ext.API_URL + 'event/view';
let obs;
return Observable
.create((o) => {
obs = o;
obs.next();
})
.flatMap(() => {
this.icons.next("loading");
console.log("executing request");
return this.http.get(url)
})
.retryWhen(error => {
this.icons.next("error");
return error.delay(3000);
})
.map((response: Response) => {
this.icons.next("ok");
console.log("response received");
setTimeout(() => {
console.log("pushing next");
obs.next();
}, 1000);
return (<any>response.json()).map(item => {
return item;
});
});
}
}

Answer Source

It might be caused by the implementation of EventService or might be an issue with ngClass but manually invoking change detection should work around the issue:

export class EventSpinner implements OnInit {
    icon: string;

    constructor(public eventsService: EventsService, private cdRef:ChangeDetectorRef) {
    }

    ngOnInit(): void {
        this.eventsService.icons.subscribe((icon) => {
            let old = this.icon;
            this.icon = icon;
            console.log("this.icon = " + this.icon + " (was " + old + ")");
            this.cdRef.detectChanges();
        });
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download