Access scope outside of AngularJS
When using AngularJS, it is considered best practice to use AngularJS directives to modify the DOM, not jQuery. Using jQuery a lot usually means that you aren't doing things the "AngularJS way" and is therefore a code smell. But what if you just have to interact directly with AngularJS using jQuery? Here's how.
First, let's create a simple AngularJS application:
<script>
var app = angular.module('app', []);
app.controller('ctrl', ['$scope', function ($scope) {
$scope.message = 'hello';
}]);
</script>
<div ng-app="app" ng-controller="ctrl">
{{message}}
</div>
This simple AngularJS application will output a blank page except for the word "hello".
The next step is to somehow get the $scope object so we can read from it and modify it. Fortunately, AngularJS provides this feature via the angular.element() extras (angular.element documentation).
We know that the $scope object that we want is attached to the div with attribute ng-controller="ctrl". We use this as the basis for a selector and then pass the string into angular.element(). Below is a function that does this. The getScope() function accepts a single argument, ctrlName, which is the name of the controller, in this case, "ctrl".
function getScope(ctrlName) {
var sel = 'div[ng-controller="' + ctrlName + '"]';
return angular.element(sel).scope();
}
The function would be used as so:
var $scope = getScope('ctrl');
Now, the above $scope variable is the exact same one that is inside of the "ctrl" controller. We can do stuff like changing the message from "hello" to "goodbye".
$scope.message = 'goodbye';
$scope.$apply();
We have to call $apply() because $scope is modified outside of the $digest cycle.
Here it is all put together inside of a JSFiddle demo.
Written by Richard McDaniel
Related protips
7 Responses
Wow nice example. Thanks lot
If u have any aliasing for ur controller....u have to do one change in calling the angular controller methods.
$scope.ctrlAliasName.methodName();
Turns out this does not work if debugInfoEnabled
is set to true since element().scope()
relies on the debugInfo
I'm having the same issue as varanisi_manoj. I want to use the methods on the $scope, but I get the error Object doesn't support property or method 'methodName'. Other than that, this is really helpful.
I take that back. Methods are on the scope as expected, but somehow this particular one that I'm trying to use isn't loaded into the scope. Weird. Thanks again!
I'm given 'Cannot read property '$apply' of undefined', can someone please help me?
THANK YOU Sir :D