How do I use services in Angular to store variables? - angularjs

How do I use services to store variables so that I can access it in previous controller on pressing back button?
For example:
.controller('myCtrl', function($scope, myservice) {
console.log(myservice.myvar.myval)
// output: undefined pressing back button
});
.controller('myCtrl2', function($scope, myservice) {
myservice.myvar.myval = "This I want in controller myCtrl on pressing back button"
console.log(myservice.myvar.myval)
// outputs the value
});
If services are not the best approach and I should use $rootScopethen will it do the job.
P.S angular.module and myservice are defined.

You need to use getter-setter for this.
For Example:
angular.module('MyModule', [])
.service('myservice', function () {
this.myval = "value";
this.getValue = function () { return this.myval }; //getter
this.setValue = function (val) { this.myval = val }; //setter
})
.controller('myCtrl', function($scope, myservice) {
console.log(myservice.getValue());
// get the value here
});
.controller('myCtrl2', function($scope, myservice) {
myservice.setValue("This I want in controller myCtrl on pressing back button");
// Set the value here
});
This is for the reference only. Please don't copy-paste and run code.

Angular services are singletons and can be freely shared among components, which have access to dependency injection. You can define a closure with a module pattern of getters and setters or directly attach properties to the object you intend to return.

I see 4 options, you can store it in a service, in $rootScope, in localStorage for persistent storage, and in sessionStorage to store datas only during the application lifetime. There's btw a nice module that wrap localStorage and sessionStorage, and make its use simpler :
http://ngmodules.org/modules/ngStorage

Related

Sharing variable globally

In my main controller I have a user service that returns the current user.
// Curr user
userService.getCurrentUser().then(user => {
mainCtrl.currUser = user;
});
Is there any way to be able to use the currUser variable in other controllers without injecting my service and calling this method over and over again in maybe 50 controllers?
Ex.
// My other awesome controller
console.log(currUser.fullName);
You could go for a LocalStorage or $rootScope. , if you are sure about not using Providers/Services
Sample:
myApp.controller('DemoController1', ['$scope', '$rootScope', function DemoController($scope,$rootScope) {
$rootScope.currUser.fullName ="test";
}]);
Then access it as,
myApp.controller('DemoController2', ['$scope', '$rootScope', function DemoController($scope,$rootScope) {
var fullName = $rootScope.currUser.fullName;
}])
you can use $rootScope like bellow:
mainCtrl.$rootScope.currUser = user;
and the other controller, you can recover this as bellow:
console.log(yourContrl.$rootScope.currUser.fullName);
You don't want you use controller injections? Use injector its the same like injections but also different :D ... like in this runnable fiddle demo. In that way you still can use services, factories, or components.
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.name = angular.injector(['data']).get('user').currUser.username;
});
angular.module('data', []).factory('user', function () {
return {
currUser: {
username: 'Alfred'
}
}
});

how to use $route.reload() commonly for all controllers in angular js

In order to retain a $rootScope value on refresh[F5] we can use $route.reload in controller as below:
$scope.reloadCtrl = function(){ console.log('reloading...'); $route.reload(); }
As i am using so many controllers, is there any way to use commonly in app.config()?
By refreshing the page you will wipe your $rootscope from memory. Your application restarts.
You can use some kind of storage. That way you can save a users preference and use it again when he comes back to you application.
You can use for example $cookies or sessionStorage / localStorage.
If you want to detect refresh on your app.run you can do by this way:
In the app.run() block inject '$window' dependency and add:
app.run(['$rootScope', '$location', '$window',function($rootScope,$location, $window) {
window.onbeforeunload = function() {
// handle the exit event
};
// you can detect change in route
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (!current) {
// insert segment you want here
}
});
}]);`
You can use a angular factory instead to have all the values across controllers
Use the below code
var app = angular.module('myApp', []);
app.factory('myService', function() {
var v1;
var v2;
var v3;
return{
v1:v1,
v2:v2,
v3:v3
});
app.controller('Ctrl1', function($scope,myService) {
});
app.controller('Ctrl2', function($scope,myService) {
});
If your using constants in $rootscope u can even use this
app.constant('myConfig',
{
v1:v1,
v2:v2,
v3:v3
});

Why can't I inject $scope into a factory in Angular?

I have a factory that needs to listen for a broadcast event. I injected $scope into the factory so I could use $scope.$on. But as soon as I add $scope to the parameter list I get an injector error.
This works fine:
angular.module('MyWebApp.services')
.factory('ValidationMatrixFactory', ['$rootScope', function($rootScope) {
var ValidationMatrixFactory = {};
return ValidationMatrixFactory;
}]);
This throws an injector error:
angular.module('MyWebApp.services')
.factory('ValidationMatrixFactory', ['$scope', '$rootScope', function($scope, $rootScope) {
var ValidationMatrixFactory = {};
return ValidationMatrixFactory;
}]);
Why can't I inject $scope into a factory? And if I can't, do I have any way of listening for events other than using $rootScope?
Because $scope is used for connecting controllers to view, factories are not really meant to use $scope.
How ever you can broadcast to rootScope.
$rootScope.$on()
Even though you can't use $scope in services, you can use the service as a 'store'. I use the following approach inspired on AltJS / Redux while developing apps on ReactJS.
I have a Controller with a scope which the view is bound to. That controller has a $scope.state variable that gets its value from a Service which has this.state = {}. The service is the only component "allowed" (by you, the developer, this a rule we should follow ourselves) to touch the 'state'.
An example could make this point a bit more clear
(function () {
'use strict';
angular.module('app', ['app.accounts']);
// my module...
// it can be defined in a separate file like `app.accounts.module.js`
angular.module('app.accounts', []);
angular.module('app.accounts')
.service('AccountsSrv', [function () {
var self = this;
self.state = {
user: false
};
self.getAccountInfo = function(){
var userData = {name: 'John'}; // here you can get the user data from an endpoint
self.state.user = userData; // update the state once you got the data
};
}]);
// my controller, bound to the state of the service
// it can be defined in a separate file like `app.accounts.controller.js`
angular.module('app.accounts')
.controller('AccountsCtrl', ['$scope', 'AccountsSrv', function ($scope, AccountsSrv) {
$scope.state = AccountsSrv.state;
$scope.getAccountInfo = function(){
// ... do some logic here
// ... and then call the service which will
AccountsSrv.getAccountInfo();
}
}]);
})();
<script src="https://code.angularjs.org/1.3.15/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="AccountsCtrl">
Username: {{state.user.name ? state.user.name : 'user info not available yet. Click below...'}}<br/><br/>
Get account info
</div>
</div>
The benefit of this approach is you don't have to set $watch or $on on multiple places, or tediously call $scope.$apply(function(){ /* update state here */ }) every time you need to update the controller's state. Also, you can have multiple controllers talk to services, since the relationship between components and services is one controller can talk to one or many services, the decision is yours. This approach focus on keeping a single source of truth.
I've used this approach on large scale apps... it has worked like a charm.
I hope it helps clarify a bit about where to keep the state and how to update it.

Angular Variable/Function Global Scope

I have a variable that i use almost everywhere in my app, in many different controllers.
I'm looking for the best possible way of setting that variable knowing that :
-The variable will need to get updated from a controller and resulting in an update on the whole app ( other controllers mainly).
-Some of those function are instance of an object with function in itself that have a callback , does that cause any issue?
So far there seems to be 2 way of doing that :
rootScope but that rarely advised apparently:
myApp.run(function ($rootScope) {
$rootScope.var = "string";
});
And building a custom directive ( but what about setting it's variable ?)
angular.module('myApp').factory('test', function() {
return {
test : 'string'
};
});
Can anyone point me in the right direction and help me choose betweem the two?
I would recommend using a service or factory save that value in someService.variable and the broadcast n event that this value has been changed. I am attaching sample code. It may contain some syntactical error but I want to give you an idea
angular.module("myapp")
.controller('myCtrl', function($scope, $rootScope, myService) {
$scope.change = function() {
myService.var = 'abc';
$rootScope.broadcast('varChanged');
};
})
.controller('myOtherCtrl', function($scope, $rootScope, myService) {
$rootScope.on('varChanged', function(e) {
use(myService.var);
});
})
.service('mySerice', function() {
this.var = '';
});

angularjs saving $scope via a closure

Disclaimer that I'm new to angularjs :)
I have a controller that delegates to a service and I'm trying to preserve the $scope so I can scope.apply after setting properties:
var Build = function($scope, $http, mango) {
var scope = $scope;
$scope.BuildManagerSubmit = function(selectedProfile) {
mango.buildMango(selectedProfile.def, function(profiledef) {
// bunch of property assignments on selectedProfile ...
scope.$apply();
}, scope);
};
};
controllers.controller('Build', ['$scope', '$http', 'mango', Build]);
Notice that I'm using the closure to save the scope and passing it in to the service (omitted for brevity). The service calls me back like cb.call(context, ...) so I maintain access to scope. This is all working fine, but I'm more concerned with whether there's a better idiom. I don't see a lot of examples of maintaining $scope when delegating out to services like this.
EDIT: this application is using node-webkit and the 'mango' service essentially is interacting with the file system to call out to shell scripts, etc.
I would make the mango service take care of that (inject $rootScope in it), and perhaps use promises to replace callbacks so it would look like that:
var Build = function($scope, $http, mango) {
$scope.BuildManagerSubmit = function(selectedProfile) {
selectedProfile.profileDef = mango.buildMango(selectedProfile.def);
// do something when profileDef returned? (not always necessary)
selectedProfile.profileDef.then(function(profileDef) {
});
};
};
controllers.controller('Build', ['$scope', '$http', 'mango', Build]);

Resources