What is the best way to store a "user" object that is accessible across all controllers in an Angular application?
I also have a function that fetches & sets the user.
Option 1: $rootScope
At first I was just setting $rootScope.user = myUser. Then in every control I could use $rootScope. This was fine, until I ended up with a lot of duplicate code since I had to check if it existed at the start of each controller.
// At the start of each controller
if (!$rootScope.user) {
// fetch and set user
}
Option 2: Angular service?
Option 3: Angular factory?
References:
angular.service vs angular.factory
I would use a factory over a service, or $rootScope.
As Ed pointed out below, both a service and a factory are singletons.
$rootScope, as the name implies is the root of all scopes in an angularjs application.
Here is something for reference: http://ilikekillnerds.com/2014/12/angularjs-service-vs-factory/
If you are creating a SPA and not creating a scope without parent then use rootScope it will work like a charm.
Related
I've been reading that Services are great for sharing data. But I am having a hard time making all data be in sync...
For example, let's say you have
an ItemService with an array of items.
a ItemListController, which shows a list of items ($scope.items = ItemService.items)
a AddItemController, a form to add items to the array (using the service).
When I add a new item, it doesn't automatically shows in the list controller. My workaround so far is to use cache:false in the router so that it refreshes every time I look at it...
I can't use $scope.$apply() because the adding happens on one controller while I want to see it on another...
You need to use $rootScope.$broadcast('item.added'); in the controller that initiates changes (AddItemController), after it successfully updates the array in the service.
Then in the ItemListController you use
$rootScope.$on('item.added', function(event){
$scope.items = ItemService.items;
});
Check this question
#Sarpdoruk There is two-way data binding between views and controllers, but not between controllers and services. By using this line $scope.items = ItemService.items; you copy 'items' from service to items in controller but you copy by value, not by reference. You can change $scope.items in your view or controller and they will get updated between the view and controller but these changes will have no effect on the service. Same thing if you update items in the service - controller will not know that something has been changed - so you need to $broadcast or $emit that something has changed from service and listen for the changes in the controller. You can also $broadcast between controllers, directives and even services (but since services have no access to $scope, you have to use $rootScope and some people frown upon that). The bottom line is, if you really have to use a $rootScope in the service because otherwise you will have to overcomplicate parts of your app, then do it and never bother with "best practice evangelist" The first rule of the app is that it has to work, only after it works you should worry about clean code. I hope it makes it clearer now.
All of the controllers in my app share a dependency on a data provider type service I created. This service consists of functions to retrieve various bits of data, and almost all of these methods allow for an optional parameter. The ability to enter in this optional parameter is role based. The problem is my controllers are now full of code similar to:
// Initializing controller.
dataservice.getRole().then(function(role) { $scope.isAdmin = role.isAdmin; });
// After a button press or some other event.
if($scope.isAdmin) {
dataservice.getData($scope.param1, $scope.param2, $scope.optionalText);
} else {
dataservice.getData($scope.param1, $scope.param2);
}
It seems a code smell to me that I have to keep repeating this code throughout the controllers, but I can't think of a way to construct my controllers where I don't have to.
That's how I've realized that: Controller Inheritance.
Basically:
Create your service (factory) with your Base Controller logic and
return the Constructor (example)
Use $injector.invoke in your derived Class (to implement your
base controller) in order to enrich the actual controller $scope
(example)
There's no an official "angular way" to implement this features, but I hope the angular team will work on it
I am facing a different problem.
According to my code I have a common service where I have written all my functions. I have injected service into 2 different controllers.
Here my Problem is I want to call the function in 2nd controller when common service executing under 1st controller. I am passing $scope variable to common service. so when service working under 1st controller $scope variable refers 1st controller only But I want to change the reference of $scope to 2nd controller..
Thanks
everybody, As you can see the title, i have to confirm my understanding, that
If we have :
angular.module('moduleName', [<Dependencies If any>]);
Then, do we really need this angular.injector, or is it just an another alternative.
If there is any other advantages of using the angular.injector, please let me know.
I have couple of other doubts.
we can use $filter in controller to get the particular filter and use its functions if any.
1. so how to use/call filters in directives.
2. how to call one controller function in another controller, is it possible?
Please Let me know the advantage of using angular.injector over angular.module('moduleName', [<Dependencies If any>]); And when it is good/needed to use it. not the implementaion of angular.injector
I needed it to get some services outside of the angular scope. For example my application is running on some legacy one. To change some parameters in the angular applicaion I needed to access an angular service from javascript outside of the angular. Then I used angular.injector to get the service.
injector = angular.element('#myangularDiv')).injector()
service = injector.get('theService')
Hi i am having the 5 pages with 5 controllers and i am using the one service using injection in every controller . Is it possible to do without editing a code in views and controllers to stop the services functionality by writing code anywhere once in the any of one view or controller ?
For example I am having a app which uses the server to retrieve the data and i can writing a simple code to restrict that service instead of server i can access my localdata ?
All Angular services are application singletons. This means, you can change state of the service once, and the change will be 'visible' to all it's users.
The service gets instantiated when application will ask for it. While the service exists, all the controllers, etc. will receive a reference to the same service instance (I would still expect the service to be garbage collected when all the references to the service are lost).
This means, after you initialize the service, all controllers can invoke methods, etc. - all on the same instance, visible to all other instances.
Here's a jsFiddle showing the concept. When the value in factory object is changed in one controller, it is visible throughout the application. Both controllers use the modified value of testFactory.name, as it gets modified during the initialization of HelloCtrl. It is fairly easy to add two buttons that would count clicks in a field of factory's object and make both controllers display the value as it changes.
function HelloCtrl($scope, testFactory)
{
$scope.fromFactory = testFactory.sayHello();
testFactory.setName("ellitereit");
$scope.newValue = testFactory.sayHello();
}
function GoodbyeCtrl($scope, testFactory)
{
$scope.fromFactory = testFactory.sayGoodbye();
}