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);
  });
7
  • Pass this controller scope as parameter to that function Commented May 4, 2016 at 5:51
  • 1
    you can use $rootscope variable place of $scope to set global value Commented May 4, 2016 at 5: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. Commented May 4, 2016 at 5:57
  • And $rootscope is the property of...? app? Commented May 4, 2016 at 5:59
  • @dreamweiver How do I access $rootScope outside of the angular app scope? Commented May 4, 2016 at 6:10

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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

3 Comments

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?
You can use the scope property in the directive definition to pass values into the directive. Refer: docs.angularjs.org/guide/directive and stackoverflow.com/a/18378602/3878940 answer on SO
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?
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

Comments

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;
}

4 Comments

The global function is being called on a script load. I can't call it unless the script has loaded.
use can use $rootScope
$rootScope is not a declared variable. It isn't available like you are using it here.
yes I know it's not declared variable. it can be set at state level and use in controller.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.