angular controllerAs(this) equivalent of $scope.$broadcast and $scope.on, - angularjs

According to this answer I just want fire event from controller to another
Call a method of a controller from another controller using 'scope' in AngularJS
$scope.$on("myEvent", function (event, args) {
$scope.rest_id = args.username;
$scope.getMainCategories();
});
And in the second controller you'd just do
$scope.initRestId = function(){
$scope.$broadcast("myEvent", {username: $scope.user.username });
};
But I don't use $scope in my application, just controllerAs and this. There is a way to fire event without inject the scope ? Or should I inject $scope anyway ?But I read in another answer that using both scope and controllerAs is bad practice.

It's not possible to register an $emit or $broadcast event without $scope or $rootScope being injected in the controller.
It is indeed bad practice to use $scope variables and functions since the instance of your controller is already injected inside the $scope with the controllerAs syntax.
But there is not other choice than injecting scope objects if you want to use these events.
However you shouldn't use $emit or $broadcast events just to share data. These events are used for application wide information (like user has logged in or logged out...etc.)
A good practice when using angular events is to prefer $rootScope.$emit because $scope relies on the hierarchy of your components.
For example:
$scope.$emit will emit to the parent component.
$scope.$broadcast will broadcast to children components.
Then $rootScope.$broadcast will broadcast events to the rootScope as well as the scope (which may make your code messy real quick)
$rootScope.$emit is to be preferred as it registers the event application wide and makes it available to the rootScope only. ($rootScope.$on)
Another good practice is to unbind your custom events.
Whenever a component or directive is unloaded/destroyed, the event listener will still reside inside rootScope resulting in possible memory leaks.
To unbind an event:
var unbind = $rootScope.$on('logout', function(event, data) {
console.log('LOGOUT', data);
});
$scope.$on('$destroy', unbind);

I think that generally overuse of $broadcast and $emit is a bad practice too. If you don't want to use the $scope, why not moving the logic handled by events to a service?

Related

change scope value in already loaded controller from another controller without rootScope

I need to update one $scope value of controller-2(already loaded) from controller-1. I don't want to use $rootScope.
Can I use broadcast or emit for same?
If the controllers are in a child-parent relationship, you can use:
$emit (if controller1 is child of controller2)
$broadcast (if controller2 is child of controller1)
If they are not in this relationship, then you need to:
emit from controller1
catch the event in the closest parent (could be the app)
broadcast new event from this parent
catch the event in controller2
Of course... this is not always the best way to go.
If you prefer, you can use other ways to communicate (e.g. use a common service).
Use brodcast on rootscope and listen on scope.
The best practice is to create a service for each custom event you want to listen to or broadcast.
.service("hiEventService",function($rootScope,$scope) {
this.broadcast = function() {$rootScope.$broadcast("hi")}
this.listen = function(callback) {$scope.$on("hi",callback)}
})
You can use $localStorage for change that value. or create one service for get and set that value.

invoking directive controller method from another directive's controller

I have a directive DirectiveA which has a method x defined inside its controller. I need to invoke this method from another directive's (DirectiveB) controller.
The problem is with the app I work on because when you need to go to a specific route, you basically invoke another directive which is then rendered by Angular. What I am looking for is to find a way to call x method after the page was rendered. That x is going to display an element on my page when it is called.
Can you help me with this?
You might want to use events, you can fire event up the scope by using $emit, or down by using $broadcast. You catch/subscribe the event using the $on listener.
So, on your directive's controller you'll listen to the event (You can also subscribe $rootScope but then you need to manually unbind the listener upon directive destroy)
$scope.$on('mySpecialEvent', function (event, data) {
... DO YOUR STUFF ...
});
And on DirectiveB you'll fire the event when you want to execute the action in DirectiveA's listener:
$rootScope.$broadcast('mySpecialEvent', 'HI');

Angularjs $rootScope.$broadcast when watch position to pass message from factory to directive

I want to create factory which will navigator.geolocation.watchPosition and everytime will broadcast to rootscope then directive will listen $scope.$on. Is there any performance issue on the way or better how way to do it? The device with this app will be on the always on the move.
Broadcast is always heavy.
Instead of broadcast, emit on the rootScope and listen on the rootScope. And when your directive scope is destroyed remove the listener from the scope.
Factory:
$rootScope.$emit('eventName:emit');
Directive:
var destroyFn = $rootScope.$on('eventName:emit', listernFn);
$scope.$on('$destroy', destroyFn);
Changed name eventname to eventname:emit to make event specific to listen $emit event.

Forcing a digest in Angular

At some point after a user action I would like to cause a digest to occur, so the UI reflects a change in the data-model backing it.
I have a service that performs some change in a callback (asynchronously).
I understand that $scope only makes sense in the context of a controller. Can I achieve the same effect by performing $apply() on the $rootScope?
I have seen code that checks for $$phase or similar related to avoiding digest errors, what checks should I perform in order to trigger a digest safely?
See this answer: Running $apply on $rootScope vs any other scope
You can call $rootScope.$apply() outside of a controller (i.e. in a service) in order to trigger a digest loop.
Alternatively, you could consider using $broadcast and $on to send a notification to other parts of your app when something needs refreshing. (See Understanding Angular’s $scope and $rootScope event system $emit, $broadcast and $on)
// in a service
$rootScope.$broadcast('myCustomEvent', {
someProp: 'foobar'
// other data
});
// in a controller or another service
$scope.$on('myCustomEvent', function (event, data) {
console.log(data);
// do something with this event
});

Why do we use $rootScope.$broadcast in AngularJS?

Tried to find some basic information for AngularJS $rootScope.$broadcast, But the AngularJS documentation doesn't help much. In easy words why do we use this?
Also, inside John Papa's Hot Towel template there is a custom function in the common module named $broadcast:
function $broadcast() {
return $rootScope.$broadcast.apply($rootScope, arguments);
}
I did not understand what this is doing. So here are couple of basic questions:
1) What does $rootScope.$broadcast do?
2) What is the difference between $rootScope.$broadcast and $rootScope.$broadcast.apply?
$rootScope basically functions as an event listener and dispatcher.
To answer the question of how it is used, it used in conjunction with rootScope.$on;
$rootScope.$broadcast("hi");
$rootScope.$on("hi", function(){
//do something
});
However, it is a bad practice to use $rootScope as your own app's general event service, since you will quickly end up in a situation where every app depends on $rootScope, and you do not know what components are listening to what events.
The best practice is to create a service for each custom event you want to listen to or broadcast.
.service("hiEventService",function($rootScope) {
this.broadcast = function() {$rootScope.$broadcast("hi")}
this.listen = function(callback) {$rootScope.$on("hi",callback)}
})
What does $rootScope.$broadcast do?
$rootScope.$broadcast is sending an event through the application scope.
Any children scope of that app can catch it using a simple: $scope.$on().
It is especially useful to send events when you want to reach a scope that is not a direct parent (A branch of a parent for example)
!!! One thing to not do however is to use $rootScope.$on from a controller. $rootScope is the application, when your controller is destroyed that event listener will still exist, and when your controller will be created again, it will just pile up more event listeners. (So one broadcast will be caught multiple times). Use $scope.$on() instead, and the listeners will also get destroyed.
What is the difference between $rootScope.$broadcast & $rootScope.$broadcast.apply?
Sometimes you have to use apply(), especially when working with directives and other JS libraries. However since I don't know that code base, I wouldn't be able to tell if that's the case here.
$rootScope.$broadcast is a convenient way to raise a "global" event which all child scopes can listen for. You only need to use $rootScope to broadcast the message, since all the descendant scopes can listen for it.
The root scope broadcasts the event:
$rootScope.$broadcast("myEvent");
Any child Scope can listen for the event:
$scope.$on("myEvent",function () {console.log('my event occurred');} );
Why we use $rootScope.$broadcast? You can use $watch to listen for variable changes and execute functions when the variable state changes. However, in some cases, you simply want to raise an event that other parts of the application can listen for, regardless of any change in scope variable state. This is when $broadcast is helpful.
Passing data !!!
I wonder why no one mention that $broadcast accept a parameter where you can pass an Object
Example:
// the object to transfert
var obj = {
status : 10
}
$rootScope.$broadcast('status_updated', obj);
$scope.$on('status_updated', function(event, obj){
console.log(obj.status); // 10
})
What does $rootScope.$broadcast do?
It broadcasts the message to respective listeners all over the angular app, a very powerful means to transfer messages to scopes at different hierarchical level(be it parent , child or siblings)
Similarly, we have $rootScope.$emit, the only difference is the former is also caught by $scope.$on while the latter is caught by only $rootScope.$on .
refer for examples :- http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Resources