Guillaume Rahbari
Guillaume Rahbari

Reputation: 43

$watch and 2 controllers

Context

I have 2 views and 3 controllers.

What I want : When I click on a button in "settings.html", I want to update my variable 'shopMarkers' in "settings.js" (variable define in "main.js") and I want also that automatically an object in "map.js" be updated using the new value of 'shopMarkers' to display markers in a map in "map.html".

Settings.html

<div class="settings">

  <div class="row">

    <div class="question">
      Show shops ?
    </div>

    <div class="switch">
      <input id="toggle-1" class="toggle toggle-round" type="checkbox" ng-click="toggleShops()">
      <label for="toggle-1"></label>
    </div>

  </div>

</div>

Settings.js

'use strict';

/**
 * @ngdoc function
 * @name frontEndOpenEatApp.controller:SettingsCtrl
 * @description
 * # SettingsCtrl
 * Controller of the frontEndOpenEatApp
 */
angular.module('frontEndOpenEatApp')
  .controller('SettingsCtrl', ['$scope', 'shops', function ($scope, shops) {

    $scope.toggleShops = function() {
      if ($scope.$parent.shopMarkers.length == 0){
        shops.getShops().then(
          function (data){
            createMarkersForShops(data);
          }, function (msg) {
            console.log(msg);
          }
        );
      }
      else {
        $scope.$parent.shopMarkers = [];
      }
    };

    var createMarkersForShops = function (shops){
      var markers = [];
      for (var shop in shops) {
        var marker = {
          position : new google.maps.LatLng(shops[shop].latitude,shops[shop].longitude),
          title : shops[shop].description
        };
        markers.push(marker);
      }
      $scope.$parent.shopMarkers = markers;
    };

  }]);

map.html

<div id="loader" class="animated fadeIn">
  <i class="fa fa-cog fa-spin"></i>
</div>

<div id="map-canvas"></div>

map.js

'use strict';

/**
 * @ngdoc function
 * @name frontEndOpenEatApp.controller:MapCtrl
 * @description
 * # MapCtrl
 * Controller of the frontEndOpenEatApp
 */
angular.module('frontEndOpenEatApp')
  .controller('MapCtrl', ['$scope', 'shops', '$timeout', function ($scope, shops, $timeout) {

    var map;
    /**
     * Initialisation de la carte google map.
     */
    function initialize () {
      var mapOptions = {
        zoom: 18,
        center: new google.maps.LatLng(48.8879996, 2.2882407)
      };

      map = new google.maps.Map(document.getElementById('map-canvas'),
        mapOptions);

    }

    $scope.$parent.$watch($scope.shopMarkers, updateShopsMarkers, true);

    function updateShopsMarkers (){
      for (var shop in $scope.$parent.shopMarkers){
        var marker = new google.maps.Marker($scope.$parent.shopMarkers[shop]);
        marker.setMap(map);
      }
    }

  }]);

main.js

'use strict';

/**
 * @ngdoc function
 * @name frontEndOpenEatApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the frontEndOpenEatApp
 */
angular.module('frontEndOpenEatApp')
  .controller('MainCtrl', ['$scope', function ($scope) {
    $scope.shopMarkers = [];
  }]);

I hope I described my problem correctly.

PS : 'shops' is a service I created, but I don't think it's relevant to describe it more. I use some google map function, but that is not the problem here neither, you can forget these functions. My problem is really about the $watch from a parent controller updated from an other child controller. And to finish I apologize for any incorrect spelling.

Upvotes: 0

Views: 88

Answers (3)

Guillaume Rahbari
Guillaume Rahbari

Reputation: 43

I found my mistake :

in map.js I wrote :

$scope.$parent.$watch($scope.shopMarkers, updateShopsMarkers, true);

The solution is :

$scope.$parent.$watch('shopMarkers', updateShopsMarkers, true);

Upvotes: 0

VizardCrawler
VizardCrawler

Reputation: 1303

You can make the shopMarkers variable available in the $rootScope and it will change accordingly if any change occurs to it.

So i would suggest inject $rootScope service and define the variable using $rootScope.

i.e

 $rootScope.shopMarkers = [];

Upvotes: 1

Muhammad Reda
Muhammad Reda

Reputation: 27023

You can do that using $scope.broadcast and $scope.$on

In settings.js

angular.module('frontEndOpenEatApp')
  .controller('SettingsCtrl', ['$scope', 'shops', function ($scope, shops) {
    // watch for $scope.shopMarkers changes
    $scope.$watch('shopMarkers', function(newValue) {
      // broadcast an event telling that $scope.shopMarkers value has been changed
      $scope.boradcast('shopMarkersValueChanged', { value: newValue });
    });
}]);

In map.js

angular.module('frontEndOpenEatApp')
  .controller('MapCtrl', ['$scope', 'shops', '$timeout', function ($scope, shops, $timeout) {
  // listen for event "shopMarkersValueChanged"
  $scope.$on('shopMarkersValueChanged', function(event, args) {
    // update the value of $scope.shopMarkers with the value sent from "SettingsCtrl"
    $scope.shopMarkers = args.value;
  });
}]);

Upvotes: 0

Related Questions