Issue
I’m trying to build a simple app with angular2, I have the below component:
@Component({
selector: 'map-menu',
templateUrl: './angular-app/components/map-menu.html'
})
export class MapMenuComponent {
@Input() selectedMarkers: Array<google.maps.Marker>;
constructor() {
// setInterval(() => {
// console.log(this);
// }, 1000);
}
}
when my map-menu.html is:
<ul class="nav nav-sidebar">
<li *ngFor="#marker of selectedMarkers #i = index"><a href="#">{{marker.data.name}}</a></li>
</ul>
and in my app html I have:
<map-menu [selectedMarkers]="selectedMarkers"></map-menu>
and the list is not being updated, BUT when I’m adding the commented setInterval it is working fine. what am I missing there?
I’ve created a plunker with the solution
Solution
From the User Input dev guide:
Angular only updates the bindings (and therefore the screen) if we do something in response to asynchronous events such as keystrokes.
I’m guessing you don’t have an asynchronous event when the markers array is updated, hence nothing is causing Angular to run its change detection algorithm.
Update: The issue was not that there wasn’t an asynchronous event, the issue was that the asynchronous event (google.maps.Marker.addListener()
) is not known by Angular, hence Zone does not monkey patch it, hence Angular doesn’t run its change detection algorithm when the data changes. The solution is to emit the event inside Zone’s run()
function:
marker.addListener('click', () => {
this.zone.run(() => {
this.markerClickEvent.next({data:{name: 'another'}});
});
});
This will cause Angular to run its change detection algorithm, notice the change, and update the view.
The reason setInterval()
works is because it is monkey patched by Zone.
See DiSol’s plunker for more details.
If you want to learn more about Zone, watch Miško’s video.
See also NgZone API doc.
Answered By – Mark Rajcok
Answer Checked By – Timothy Miller (AngularFixing Admin)