6

Is it possible to set a $scope variable of a controller from outside the controller?

For example, if I have a controller:

app.controller('citySelectCtrl', ['$scope',function($scope){

}]);

And a function in the global scope which has an event handler. Now I want to set a $scope variable when that event happens. Is it possible? My global function:

function initAutocomplete() {
    autocomplete = new google.maps.places.Autocomplete(
        /** @type {!HTMLInputElement} */(document.getElementById('autocomplete')),
        {
            componentRestrictions: {'country': 'in'},
            types: ['(cities)']
        });
    map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: 22.5937, lng: 78.9629},
        zoom: 5,
        minZoom: 5
    });
}

autocomplete.addListener('place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    if (!place.geometry) {
      window.alert("Autocomplete's returned place contains no geometry");
      return;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17);  // Why 17? Because it looks good.
    }
----------------------------------------------------------
    //SET $scope.city = place here
----------------------------------------------------------
    infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
    infowindow.open(map, marker);
  });
ayushgp
  • 4,891
  • 8
  • 40
  • 75
  • Pass this controller scope as parameter to that function – Sachin K May 04 '16 at 05:51
  • 1
    you can use $rootscope variable place of $scope to set global value – ram singh May 04 '16 at 05:51
  • like @ramsingh mentioned `$rootScope` is a global variable which can be used across all controllers in your module unlike `$scope` which is specific to current controller. – dreamweiver May 04 '16 at 05:57
  • And $rootscope is the property of...? app? – ayushgp May 04 '16 at 05:59
  • @dreamweiver How do I access $rootScope outside of the angular app scope? – ayushgp May 04 '16 at 06:10
  • `$rootScope` is the scope variable for your angular module, which means you cant access it outside your angular app, but you can access it anywhere in your module app , in controller, services,etc., – dreamweiver May 04 '16 at 06:20
  • Have you tried [Angular Google Map directives](https://angular-ui.github.io/angular-google-maps/#!/api/google-map) I think this might help you. – Maverick May 04 '16 at 06:23

6 Answers6

3

We can use $injector for accessing Angular Services Outside Scope. For your example.

// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
  map.fitBounds(place.geometry.viewport);
} else {
  map.setCenter(place.geometry.location);
  map.setZoom(17);  // Why 17? Because it looks good.
}
----------------------------------------------------------
    var elem = angular.element(document.querySelector('[ng-app]'));
    var injector = elem.injector();
     var $rootScope = injector.get('$rootScope');   
     $rootScope.$apply(function(){
       $rootScope.city = place //or city;
     });
----------------------------------------------------------
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});

and in your controller you could use.

app.controller('citySelectCtrl', ['$scope','$rootScope',
    function ($scope,$rootScope) {         
         $rootScope.city = {};

    }
]);

DEMO

For more details view this

Hope this helps

M. Junaid Salaat
  • 3,765
  • 1
  • 23
  • 25
0

use can use $rootScope like this.

app.controller('citySelectCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
    //$rootScope.city = place here;
}]);

and use can access the variable in global function

function initAutocomplete() {
    //$rootScope.city = place here;
}
Durgpal Singh
  • 11,481
  • 4
  • 37
  • 49
0

You can try using $broadcast from the $rootscope to notify your controller that the event has occurred.

//rootscope
$rootscope.$broadcast("myevent",eventObjectToBePassed);

//your controller
$scope.$on("myevent",function(eventObject){

//do something

});

A cleaner way would be to inject rootscope in a service and create a sendEvent function to actually do $rootscope.$broadcast.

Maverick
  • 454
  • 2
  • 11
0

You should not use a global scope variable directly when working with angular apps. The way it is recommended is to wrap this functionality in a directive and use the directive in your templates. This way you will hvae access to the $scopeto update the value. E.g.:

angular.directive('mapAutoComplete', function () {
  return {
    restrict: 'E',
    link: function (scope, elem, attr) {
      // Add your map and autocomplete here

      // Now you can use the `scope` to update the $scope of the parent controller
    }
  }
});

In your html, use the directive like this:

<map-auto-complete></map-auto-complete>

This will make the scope from the controller of the containing view available as scope within the directive

Refer these for best practices on using directives over direct dom manipulation and reusable functionality http://ng-learn.org/2014/01/Dom-Manipulations/ https://stackoverflow.com/a/15012542/3878940

Community
  • 1
  • 1
Aditya Singh
  • 15,810
  • 15
  • 45
  • 67
  • I need to give the Google maps API a callback to call when the script loads. How should I give it a non global function? – ayushgp May 04 '16 at 05:53
  • You can use the `scope` property in the directive definition to pass values into the directive. Refer: https://docs.angularjs.org/guide/directive and http://stackoverflow.com/a/18378602/3878940 answer on SO – Aditya Singh May 04 '16 at 05:56
  • This is where the call back goes: `script(src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&callback=**initAutocomplete**&libraries=places", async, defer)` What should I replace it with? – ayushgp May 04 '16 at 05:57
0

I can think about two ways to do this

  1. Use the $rootScope which is the easy way to do it. But I personally don't like it to much if it isn't really a global variable.

  2. Write a Eventhandler and listen in the controller

Philipp Beck
  • 449
  • 2
  • 14
0

You can use var requiredElemScope = angular.element(ELEMENT_SELECTOR).scope(); to get the scope of the element. Then you can assign value to the scope variable as requiredElemScope.city = someValue;

Here ELEMENT_SELECTOR is the dom selector to which the controller is attached.

Ankit Agarwal
  • 1,350
  • 10
  • 15