angular-ui / angular-google-maps

AngularJS directives for the Google Maps Javascript API
http://angular-ui.github.io/angular-google-maps
2.52k stars 1.07k forks source link

ui-gmap-circle directive with center, defined by "GeoJSON Point" has not two-way binding #1679

Open AbstractVisions opened 8 years ago

AbstractVisions commented 8 years ago

If ui-gmap-circle directive with center, defined by "GeoJSON Point", then external changes of object aren't reflected in the gmap window http://plnkr.co/edit/ZgUWZFf8DVWH8w5Dhv0Y?p=preview

if center, defined by object containing latitude and longitude properties, then it's work ok.

AbstractVisions commented 8 years ago

Сause of this issue in that using $watchCollection for "GeoJSON Point" object ("center" attr of ui-gmap-circle directive) , instead of use of $watch with objectEquality=true, which is correctly used for Marker "GeoJSON Point" object ("coords" attr of ui-gmap-marker)

It is an issue or the design decision?

nmccready commented 8 years ago

Yes because $watch adds unnecessary load and weight to the directive. Just clone the center getting a new reference and modify that. Another option would be extending the directive (all of them) to allow you to choose the watch function. IE ($watch, $watch (deep), $watchCollection, and no watch (manual updates)).

AbstractVisions commented 8 years ago

Thanks for an explanation!

I already tried to use object cloning, but faced the problem reflected to start cloning in $timeout. the reason of a problem is as follows: angular-google-maps/src/coffee/directives/api/models/parent/circle-parent-model.coffee

@setMyOptions = (newVals, oldVals) =>
        return if scope.settingFromDirective
        unless _.isEqual newVals,oldVals
          gObject.setOptions @buildOpts GmapUtil.getCoords(scope.center), scope.radius

namely in comparing on equivalence. And $watchCollection specific issue, that i explane in https://github.com/angular/angular.js/issues/13799

AbstractVisions commented 8 years ago

If at first to clone center, and then to change it - that it works, but if already there were changes of center (for example in other directive, and in other quite widespread cases), the subsequent cloning will lead to that: _isEqual newVals,oldVals will be always true, and don't run internal changes.

The easiest way to correct it - add object reference check of object (and it is even better - check reference to "coordinates" property) to unless, like this: unless _.isEqual newVals,oldVals and newVals == oldVals and (newVals? and oldVals? and newVals.coordinates == oldVals.coordinates)

Perhaps such condition should be used and in other places where "geoJSON" can be used without deep $watch

I think such enhancement it will be useful also for other angular-google-maps users