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.
Related
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/
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.
I'm a newbie to Angular and I'm struggling to understand how views are updated with scope changes. I am trying to update a header in my app using Angular JS based on whether a user is logged in. This information is returned by a Login service.
I have distilled my problem into two plunkers, one working and one not.
In order to get it to work I have to assign my LoginService to a variable on the scope of the HeaderCtrl.
angular.module('app', [])
.controller('HeaderCtrl', function ($scope, LoginService) {
$scope.loginService = LoginService;
$scope.$watch('loginService.isLoggedIn()', function(newVal) {
$scope.isLoggedIn = newVal;
});
Here is the working version
http://plnkr.co/edit/KBzE9N?p=preview
Now if I remove the reference to the LoginService in the scope of the HeaderCtrl and just use the injected service in the watch directly, the view stops updating. That is demonstrated here
http://plnkr.co/edit/IjFS2w?p=preview
Can anyone explain to me why the second case doesn't work? I've also read that it is a bad idea to have watches inside a controller so I'm open to better solutions.
Because the $watch watches scope variables in the scope you are calling it from. In your second example, $watch is looking for a LoginService variable in your scope, which of course does not exists.
I was told if you need to share between controllers you should use a service. I have controller A, which is a list of news websites, and controller B which is a list of articles on the sites from controller A. Controller B contains the list of articles and an iframe to display the articles. But when you click on controller A it should fade out the iframe and fade in the list. In order to accomplish this I give Controller B's scope to a service that is injected into both controller A and controller B. My question is whether or not it's okay to do that.
Basically, I do this:
app.factory("sharedService", function () {
var $scope = null;
return {
SetScope: function (scope) {
$scope = scope;
},
ControllerB_Action: function () {
$scope.doSomething();
}
};
});
app.controller("controllerA", ["$scope", "sharedService", function ($scope, sharedService) {
$scope.onaction = function () {
sharedService.ControllerB_Action();
}
}]);
app.controller("controllerB", ["$scope", "sharedService", function ($scope, sharedService) {
sharedService.SetScope($scope);
}]);
I would say its not a good pattern, since basically, the $scope is an Object that represents your current view or DOM-State. A controllers (and/or Link-Functions of directives) are the Glue between this state and your Application-Logic - so in my opinion, the $scope-Object should always remain inside the Controllers/Links.
Therefore if you wanna share Data between 2 Controllers, you should extract what you wanna share inside the Service, but not put the whole scope there (since it has lots of additional information that you dont need and want inside both controllers).
What you can do is simply link the data you wanna share by reference - that way, your Service will also Sync the Data between the two Scopes.
There's probably a world of ways of doing this, but I'll tell you what I would do:
I'd make use of event emmiters.
Disclaimer: I haven't tested this code
Assuming that Controller B is nested in Controller A:
Controller A
var controllerBFunction_A;
$scope.$on('EventFromControllerB',function(data){
controllerBFunction_A = data.sharedFunctions.controllerBFunction_A;
});
Controller B
$scope.$emit('EvenFromControllerB',{
sharedFunctions: [
controllerBFunction_A,
controllerBFunction_B,
someOtherObject
]
});
I think this could work. In my opinion this has the benefit of selecting what you want to share between those controllers...but probably there's a more elegant way of doing this.
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/