1

I am using NgMap to display google map and I need the ability to change center position from varios parts of site. I have markerService for that:

 angular.module('markerService')
        .factory('MarkerService', MarkerService);
    MarkerService.$inject = [];
    function MarkerService(){
        var coords = [
            56.936,
            23.12
        ]
        var markers = [];
        return {
            setCoords: setCoords,
            getCoords: getCoords,
            setMarkers: setMarkers,
            getMarkers: getMarkers,
        };

        function setCoords(a){
            coords = a;
        }
        function getCoords{
            return coords;
        }
        function setMarkers(a){
            markers= a;
        }
        function getMarkers(){
            return markers;
        }
   }

Then I have component map, that uses NgMap:

    angular.module('map')
        .component('mapComponent', {
            templateUrl: 'app/mapComponent/map.html',
            controller: mapController
        });
    mapController.$inject = ['NgMap', 'MarkerService'];
    function mapController(NgMap, MarkerService){
        var ctrl = this;
        ctrl.markers = MarkerService.getMarkers();
        ctrl.center = MarkerService.getCoords();
    }
}

and template:

<div class="map_wrapper">
    <ng-map default-style="false" 
            center="{{$ctrl.center}}"
            zoom="10"
            >
        <marker ng-repeat="m in $ctrl.markers" position="{{m.lat}},{{m.lng}}" on-click="$ctrl.openModal()"></marker>
    </ng-map>
</div>

If I change markers array using MarkerService.setMarkers([...]) the markers on map are updated because ng-repeat sets watcher but changing coords with MarkerService.setCords([...]) does not change center of map because there is no watcher.

I tried using ng-bind center="ng-bind='$ctrl.center'" but logically it did not work. I am sure that I have to set watcher from components controller, but I fail to do that whatever I try.

UPDATE:

Did some serious investigation and bumped into some weird behavior.

MarkerService.getCoords() does not return an instance of coords but value. If I make changes to coords using MarkerService.setCoords(//some value) it is not reflected in variable that previously was declared var ctrl.center=MarkerService.getCoords(); but if I call getter again, I get updated value.

It is strange because I have been using this getter and setter approach a lot before and always rely on fact that getter would return an instance of variable.

Kārlis Janisels
  • 1,265
  • 3
  • 18
  • 41

2 Answers2

1

If you want to set a watcher you have to use $scope.

To do that, you need to inject it in your controller:

MarkerService.$inject = ['$scope'];

And then add your watcher:

function MarkerService($scope){
    $scope.$watch([...]);
}

But the problem you have doesn't seem to come from here, I think you are setting the coordinates on the wrong object, that is why your map is not updated.

Do you do it like this ?:

MarkerService.setCoords(coords)
ctrl.center = MarkerService.getCoords();
Groben
  • 1,374
  • 2
  • 10
  • 29
  • Yes that is exactly how I do it. Still dont get where Exatcly should I use $watch? Should I now attach every variable(markers, coords) to $scope of MarkerService? – Kārlis Janisels Apr 05 '17 at 08:56
  • Are you sure about what is returned by MarkerService.getCoords(); ? – Groben Apr 05 '17 at 08:59
  • take a look at this: http://stackoverflow.com/questions/27854833/cant-center-google-map-with-ionic-framework-and-ngmap maybe setCenter is what you need – Groben Apr 05 '17 at 09:01
  • Yes, I have checked that. In example above I set `var coords = [ 56.936, 23.12 ]` and that value is returned but when I user MarkerService.setCoords(newCoords) it changes coords in MarkerService but change in not binded on map. – Kārlis Janisels Apr 05 '17 at 09:02
  • Hm, I will look into that, however NgMap has been made in way to work together with AngularJS like in [this](https://ngmap.github.io/#/!map_with_dynamic_center.html) example. I have exposed only question-relevant part of code, the rest of code relies on method that I am trying to implement – Kārlis Janisels Apr 05 '17 at 09:07
  • Maybe the problem comes from the new array ? ctrl.center[0] = MarkerService.getCoords()[0]; ctrl.center[1] = MarkerService.getCoords()[1]; – Groben Apr 05 '17 at 09:10
  • No that is not it. I did more tracking and updated the question. Could you look into it? – Kārlis Janisels Apr 06 '17 at 13:05
  • Can you make a fiddle ? – Groben Apr 06 '17 at 13:10
  • I will try to do that. Meanwhile I updated question again - there was not "sometimes" behavior but consistent - getCoords does not return instance – Kārlis Janisels Apr 06 '17 at 13:26
  • [Here](https://plnkr.co/edit/AiEkvconQXtUrA2vZPKU?p=preview) is a plunker of problem. I included UserService as well to ilustrate the techique I am using and that it works. There must be some error in way I define MarkerService but I can not find it. I even rewrote the whole code for MarkerService but still the same issue – Kārlis Janisels Apr 07 '17 at 07:54
  • I updated your plunkr: https://plnkr.co/edit/dhsYL8M5zYU1yuNjAQRh?p=preview – Groben Apr 07 '17 at 08:33
  • Well thanks, but isnt that an hack where there shouldnt be one? I mean creating copy every time? UserService getter returns instance of object, why MarkerService is acting differently? This will not work for me because I will use the same techique with markers(where there is going to be a lot more data) – Kārlis Janisels Apr 07 '17 at 08:49
  • It is not a hack. It is to separate your form from the object, otherwise the modification is done without clicking the button. If you want that, don't create the copy and use only one object. – Groben Apr 07 '17 at 09:07
  • Oh I just unterstood your problem (the fact that you didn't want to refresh the object), you need to unterstand than when you do coords = a. you break the reference from the object. You can do this instead: https://plnkr.co/edit/WcTDWUgTVjfCpJJtNQvb?p=preview – Groben Apr 07 '17 at 09:20
  • Thank you - this is what I missed! This is exactly what I was looking for! Just to understand - is there any way to assign whole object not only property of it? – Kārlis Janisels Apr 07 '17 at 09:39
  • Nope, otherwise the reference is broken. You already do it this way in UserService, this is why it work and this is why it was tricky for me to unterstand that it was what you wanted. I prefer to use copies when working with a form but in your case, I guess you have to set the properties. – Groben Apr 07 '17 at 09:47
  • Thank you for helping. I accepted your answer while the real answer is here in comment.... – Kārlis Janisels Apr 07 '17 at 09:51
0

To complete @Groben's answer (because I faced the same problem...), the rigth syntax for $watcher in a component is:

$scope.$watch('$ctrl.my_field', function () {
    ctrl.my_function(ctrl.my_field);
});

where:

  • "ctrl" is the default name of the controller
  • don't forget to inject "$scope" !

For memory, the template looks like:

<input type="text" ng-model="$ctrl.my_field" >
Didier68
  • 1,027
  • 12
  • 26