$rootScope in angularjs custom property gone after injection - angularjs

Problem Related codepen
I declared $rootScope.myproperty in main controller and it can be accessed in other controllers.
But in one of the controller I have to inject $rootScope as I used $watch. Then when I check back $rootScope.myproperty it became undefined. Strange why would this happens?

It was happening because you were using $rootScope as a variable and assigning an object to it
$rootScope = { myproperty: 'root abc' };
This is wrong. Instead you should add attributes to it as below and it will work:
$rootScope.myproperty = 'root abc';
I have updated the codepen and its working : http://codepen.io/anon/pen/RaeyJm

Working Demo
The problem is you have injected $rootScope into AttendeesCtrl controller. You don't need to inject $rootScope into a controller. When you inject $scope, you automatically get access to anything defined in $rootScope due to the prototypal inheritance of JavaScript. So AttendeesCtrl controller should look like this:
.controller('AttendeesCtrl', function($scope) {
//I used $watch and $rootScope somehere so I have to inject $rootScope in this controller
$scope.myproperty = $rootScope.myproperty;
});
For detail, you can have a look at the AngularJS Scope Hierarchies.
Hope that solve your problem.

Related

What is the disadvantage of using the $scope as variable in angularjs, to share $scope of a controller inside the app.run?

What is the disadvantage of using the $scope as variable in AngularJS, to share $scope of a controller inside the app.run()?
Actually I am doing that to make code generic to be called from all the controllers with same function in app.run().
The function I am using is with the
$rootScope.getUserInfo = function($scope){
$scope.userinfo = '---------';
}
where $scope is the variable that I am passing from every controller like that
$rootScope.getUserInfo($scope);
I don't think there's inherently something wrong with passing around a scope. People do this a lot in AngularJS services and it's internally done a lot, too: your created controller is passed a scope to work with.
However, I would say it's not necessary in your example to have getUserInfo to depend on a scope being passed. Why not return the user information and have the caller put it on the scope? That way, you can use it in parts of your app that don't have a scope.
Instead of using $scope, you can use var vm = this; and define everything in that controller with vm.variablename_or_funcname instead of $scope.variablename_or_funcname
And you can attach that controller in html like ng-controller = "mycontroller as vm"
More info:
https://johnpapa.net/angularjss-controller-as-and-the-vm-variable/

Can we use more than one $rootScope in angularjs

In my app Im using two $rootScope in the controller. One $rootScope is inside the function and another one is outside the function. Is it possible to use two $rootScope inside the controller and also when I use the $rootScope declared inside the function Im getting error stating that particular $rootScope is not declared. How to access the second $rootScope outside the function. So that I can perform splice action on it. Please do help to solve this. Thank you. :)
My Controller:
serviceApp.controller('carBrand',['$scope','carRepository','$rootScope','$state', function ($scope, carRepository, $rootScope, $state) {
$rootScope.carSelect = carRepository.data; //First rootScope
$scope.newCarList = [];
$scope.selectItem = function (key) {
$rootScope.selectInput=key; //second rootScope
$state.go('app.carEdit',{object:key});
return(key);
}
There's only one $rootScope, it can be access everywhere injecting it in your controller.
If you want to share data between controllers, what you need to use is a service and inject it in the same way you inject $rootScope.

bindToController how to get rid of all the $scope ($scope.$on)

I'm implementing an AngularJS directive on Angular 1.4.12 using the controllerAs and bindToController "pattern" in order to have a clean controller which doesn't depend on $scope.
However I still find hard to get rid of $scope on these lines:
$scope.$on( '$destroy', function() {...} );
$scope.$on( '$stateChangeSuccess', function() {} );
Any idea how to handle this case?
Thanks
The idea behind not using $scope is to:
not pollute the HTML with variables that have no context and potentially have conflicting variable names in the same scope.
ng-model="name" VS ng-model="userController.user.name"
not pollute you javascript code by preceding every variable and
function with $scope
If you need to broadcast events or watch changes, it's perfectly fine to use $scope (especially if you have no alternative like .components in angular 1.5)
See $scope as a service provided to you by Angular just like $window or $state.
If you need it, you can use it. (but don't go and put code in there, even if you can)

vm.$on undefined error in angularjs

I am following this best practice style guide for angular development and I can't seem to get this one part working cleanly.
Best Practice Style Guide:
https://github.com/johnpapa/angular-styleguide
It recommends to declare controllers by the following:
angular
.module('app')
.controller('feedController', FeedController);
function feedController(){
var vm = this; //My $scope variable
}
The problem is I am trying to use $on to add an event listener but it gives me an undefined error for vm.$on. A temporary solution I found was to inject $scope into the controller by the following:
FeedController.$inject = ['apiservice', '$scope'];
and call $scope.$on which works but I feel its inconsistent now. Is there a way to still use vm in a clean way.
You can see the full controller here https://github.com/bliitzkrieg/TrailerFeed/blob/master/app/components/feed/FeedController.js
this/vm refers to the instance of the controller, not the scope that is associated with that controller.
Events only exist on scopes, so to use the event system it is correct to inject $scope to get a reference to the controller's scope where $on is available.
angular
.module('app')
.controller('feedController', FeedController);
function feedController($scope){
var vm = this; // the instance of the controller
$scope.on(...) // the controller's scope
}

angular js how can I use a collection in all of my scopes

I have a collection that I need to access in all of my nested scopes. Inside my directive templates, inside my directives in ng-repeat... n levels deep. I don't want to have to say $scope.$parent.$parent.$parent....$parent.MyList.
I've tried using $rootScope, but clearly I lack the understanding of how this works. I pass it into my directive during the declaration like so:
$rootScope.MyList = ["list": 1];
...
...
MyApp.directive('mydirective', ['$rootScope', function ($rootScope) {
return {
restrict: 'A',
replace: false,
link: function (scope, rootScope) {
}
}
}])
The rootScope does not contain MyList. Is there something I'm doing wrong, or a better way to do it? I've thought of using a Factory or Service, but I don't know how to set that up and we all know how crappy the documentation is for Angular, so searching is very frustrating.
Can you provide a plnkr or jsfiddle reproducing this behavior? I can get the controller to communicate with service using $rootScope.
http://plnkr.co/edit/IEhOde
However, you'd probably want to create a service which would cache the value that you want and inject it in your directive and retrieve the value.
First of all $rootScope.MyList = ["list": 1] has syntax error, should be $rootScope.MyList = ["list", 1] or $rootScope.MyList = [{"list": 1}].
Anything you assign to $rootScope is accessible within child $scopes (except isolate scopes) due to prototype inheritance.
Generally if you want to share something within whole app, you can assign it to $rootScope as you did or you can create top level AppCtrl which will have something like $scope.MyList=... and all nested scopes will have access to it. Second option is bit better when it comes to testability as you can inject service to AppCtrl which provides MyList data. You can see this pattern in action here AngularJS GlobalCtrl vs $rootScope vs Service.
A service/provider is the recommended approach.
For just a list of data you can use the value provider:
app.value('listService', {
MyList : {"list": 1}
});
Inject it where you need it, and you can include it in the relevant scopes as such:
app.controller('Ctrl', function($scope,listService) {
$scope.list = listService.MyList;
});
A fiddle of that: http://jsfiddle.net/qKcQL/
Injecting it where you need is good for documentation and maintenance. But if you really need this on the global $rootScope then this will accomplish that:
app.controller('Ctrl', function($scope,listService,$rootScope) {
$rootScope.list = listService.MyList;
});
$rootScope fiddle: http://jsfiddle.net/qKcQL/1/

Resources