Reputation: 3272
I am new bie with AngularJS.
I am trying to call function from another controller.
I found that there are sever ways to do that.
1) Shared Service
2) Using Events
Here is the link that i already checked out.
Can one controller call another
How do I inject a controller into another controller in AngularJS
I think that using events is better approach. Apart from that i think when we use $rootscope it is not destroying event reference right?
var myModule = angular.module('myapp', []);
myModule.controller('otherController', function($scope) {
$scope.$on('ShowDialog', function(event) {
alert("hello");
});
});
myModule.controller('myController', function($scope) {
$scope.OnClick = function() {
alert("Done");
$scope.$emit('ShowDialog');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div style="padding: 0 5px; height: 100%" ng-app="myapp">
<div style="padding: 0 5px; height: 100%" ng-controller="myController">
<input type="button" ng-click="OnClick()" value="Say Hello!" />
</div>
</div>
Please let me know what i am missing? And what is the best way to do it?
Upvotes: 4
Views: 6130
Reputation: 4360
There's a couple reasons why your snippet doesn't work.
You don't instantiate otherController
so there's no way it will execute any code at all. So you need to add a div with ng-controller="otherController"
Now that you have an instance of the 2 controllers, to communicate with $scope events ($emit, $broadcast, $on) they need to be nested because scope events depend on the hierarchy of elements.
$scope.$emit will register events to parent controllers.
$scope.$broadcast will register events to child controllers.
You can manipulate the snippet below by moving the nested div out and changing events type.
var myModule = angular.module('myapp', []);
myModule.controller('otherController', function($scope) {
$scope.$on('ShowDialog', function(event) {
alert("hello");
});
});
myModule.controller('myController', function($scope) {
$scope.OnClick = function() {
alert("Done");
$scope.$broadcast('ShowDialog');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div style="padding: 0 5px; height: 100%" ng-app="myapp">
<div style="padding: 0 5px; height: 100%" ng-controller="myController">
<input type="button" ng-click="OnClick()" value="Say Hello!" />
<div ng-controller="otherController"></div>
</div>
</div>
If the way your application is built prevents you from nesting controllers, you can use $rootScope events.
They work like this:
$rootScope.$broadcast will broadcast events to the rootScope as well as the scope. This will make your code messy real quick because any scope of any controller can watch for this event.
$rootScope.$emit is to be preferred as it registers the event application wide and makes it available to the rootScope only. ($rootScope.$on)
This said, it is considered bad practice to use $scope or $rootScope events for simple data manipulation that does not make sense application wide.
For example you want to tell your application that user has logged out, then it makes sense to broadcast it to the application as a whole.
But if you just want 1 controller to know some random data has been loaded, then use a service. (ex: the statistics controller doesn't need to know that a user has changed his profile picture)
It's considered bad practice because you will end up with a lot of events registered from different controllers, you will have conflicting event names and eventually it will be very hard to maintain.
If you still want to stick to events, you should remember to unbind them or you will have memory leaks issues and other nasty bugs:
var unbind = $rootScope.$on('logout', function(event, data) {
console.log('LOGOUT', data);
});
$scope.$on('$destroy', unbind); //when your controller is unloaded, unbind the events
Upvotes: 7
Reputation: 700
the example you've posted, if you're asking why it's not working, it's because each controller has it's own scope. you're emitting 'ShowDialog'
from myController
and checking it in otherController
. but ShowDialog
will only be available in myController
. that's the exact reason why we use emit
on $rootScope
, because it's golbal and can be accessed in any controller.
These are the few ways i know of to achieve what you're asking. take a look and let me know if it helps.
Upvotes: 0