I have a component that subscribes
to an Observable
from a service
. When the observable
emits its next
value some change happen in my component. The strange thing is that the component will or will not update the view depending on how the next
value has been generated. If I understand this correctly some events have been monkey patched by angular 2 as to trigger change detection and some haven't been. MIDI event are one of those that haven't (which makes kinda sens).
If the service looks for click events in order to trigger the next value, the change is reflected in the view. Therefor the change detection happens.
If the service looks for keyboard events same thing, the change detection happens.
However, when the service use a MIDI event, no change detection happens.
Here some code :
export class App {
arr = [
{id: 1, status: false},
{id: 2, status: false},
{id: 3, status: false}
];
thing = new Subject<boolean>();
constructor(private renderer: Renderer,
private ser:Ser,
private midi: MidiService) {}
ngOnInit(){
// listening to click events, will trigger change detection
this.renderer.listenGlobal('document', 'click', (event) => {
console.log("Left click", event);
this.thing.next(1);
});
this.thing.subscribe( v => this.toggle(v));
// my midi service events will call the toggle method however the
// changes won't be displayed in the view
this.midi.notesPayed$.subscribe(v => this.toggle(v));
}
And here is a plnkr :
https://plnkr.co/edit/SS6jwgQg4TVdOCC05cNV?p=preview
I'm not sure if this is a bug or a feature from the underlying workings of angular 2. In any case I would like to know why this happens. The concrete issue is easily resolvable by calling the change detection myself, so I don't need a solution.
That's known behavior. The MIDI API is not covered by zone.js and therefore Angulare doesn't get notified to run change detection.
Either inject
zone:NgZone
and wrap the code that changes the model withthis.zone.run(() => {...})
or inject
cdRef:ChangeDetectorRef
and invoke change detection after the change by callingthis.cdRef.detectChanges()