ngx-leaflet: Angular UI not updating after 2.6.0
The UI on the same page as the map stopped updating after upgrading past 2.5.0. I need to update variables that affect the UI outside leaflet on click events from buttons inside marker popups. I have a button in popups, that opens a dialog in the Angular HTML component.
I tried to go around this issue by adding manual calls to ChangeDetectorRef.detectChanges(), and while that worked for the popups, regular Angular UI stopped partly updating.
When the user clicks a button inside the marker popup, a dialog is opened by setting this.dialogOpen = true.
Angular template: <div *ngIf="dialogOpen"><button (click)="dialogOpen = false">Close</button></div>
Clicking the close button does not close the dialog after 2.6.0, unless the user interacts with other page elements that cause a change detection.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 1
- Comments: 18 (8 by maintainers)
(Updated)
Having to trigger change detection is by design (at least by design due to a change made in 2.6.x). Admittedly, this change was not backwards compatible, but I didn’t realize it would be this much of an issue.
There’s a description of the reasoning in the README. It’s due to a performance issue that you may or may not be aware of (you can also see https://github.com/Asymmetrik/ngx-leaflet/issues/110 for context). Basically, Angular monkey patches code into all interaction event callbacks so that it knows when it might need to run change detection.
Leaflet specifically registers a callback on mousemove, which means that change detection is triggered on all mouse move events. You can see that issue above to see some example code that describes the issue. I’ve never really noticed the actual performance impact, but it all depends on what you’re doing.
The “fix” is to run Leaflet outside of Angular’s zone. This prevents Angular from monkey patching registered event callbacks. But, it also has the side effect that those registered callbacks will no longer trigger change detection when you modify things.
There are two solutions (theoretically):
The first is to manually call
detectChangeson a reference toChangeDetectorRef. @chriszrc shows how you’d do that and I think it’s in hte README now.The second is inject
NgZoneand then wrap your changes in a call toNgZone.run(). I think this will have the same end result as the above.I can/will provide a tutorial with more details and add more explanation to the README to make sure this is clear. I also plan to fix this (or at least deal more fully with it) soon.
I was torn about making this change, or making it something that you have to opt into, so that it isn’t confusing to people who don’t care about the performance impact. That decision is TBD, but I hope to do it soon (next couple weeks). For now, you can use 2.5.x. If you need an ng5 build, I can prioritize backing the change out of 3.x so an ng5 build is available. But, I believe that 2.x is compatible with ng5 already, so that shouldn’t be necessary.
Thanks for your patience and understanding.
@reblace Hey, thanks for your contribution towards this issue ! I believe the 2nd solution you mentioned (the one with
NgZone.run()) should also be mentioned in the README. At first I opted for thedetectChangesway, but as the component containing Leaflet also had other child components, they were considerably slowed down. I was able to solve this by usingNgZone.run(), which in my opinion is also way more precise.