I know that angular services are singeltons but I have an application in which I want that each directive instance will have a different service object which will hold context. How can it be achived?
You can use a factory that returns the constructor the class that you need, later just inject it to the controller and instantiate it.
app.factory('demoClass', function() {
return {
sayHello : function() { console.log('hello') }
}
});
At controller:
function myController($scope, demoClass)
{
var test = new demoClass();
test.sayHello();
}
Related
I wonder how can i use factory inside a provider for using it inside config.
Since i understand config can be injected only with providers - i wonder how can i achieve the following functionality
app.provider('getUserLanguageProvider',['$injector', function($injector) {
this.$get = function(getUserLang) { // calling a factory
var userLang = getUserLang.getLang()
return {
getLang: function() {
return userLang
}
}
};
}]);
app.config(['$translateProvider', 'getUserLanguageProvider', function ($translateProvider, getUserLanguageProvider) {
const lang = getUserLanguageProvider.getLang() // get the language key from provider
$translateProvider.preferredLanguage(lang); // set the language key brought by getUserLang.getLang() factory
}]);
I've tried many versions of what i've described - but none works.
Don't append Provider to the provider name. Simply use the name of the service:
̶a̶p̶p̶.̶p̶r̶o̶v̶i̶d̶e̶r̶(̶'̶g̶e̶t̶U̶s̶e̶r̶L̶a̶n̶g̶u̶a̶g̶e̶P̶r̶o̶v̶i̶d̶e̶r̶'̶,̶[̶'̶$̶i̶n̶j̶e̶c̶t̶o̶r̶'̶,̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶$̶i̶n̶j̶e̶c̶t̶o̶r̶)̶ ̶{̶
app.provider('getUserLanguage',['$injector', function($injector) {
this.$get = ['$http', function($http) { // calling a factory
var userLang = getUserLang.getLang()
return {
getLang: function() {
// ....
}
}
}];
}]);
The $injector service will automatically append the Provider suffix to the configuration object. The configuration object will then be injectable into .config functions as the name of the service appended with Provider as a suffix.
code taken from here http://plnkr.co/edit/jcOwg8HgBGPtod4yCR5j?p=info
i read the below code but still i have confusion that how notifytwo's instance is getting pass to factory notify ?
factory notify has function called sampleFun which call function sampleFunTwo of another factory called notifytwo but i have not found when and how notifytwo's instance is getting pass to factory notify ?
please help me to understand the code flow. thanks
var myModule= angular.module('MyServiceModuleOne', ['MyServiceModuleTwo']);
myModule.controller('TestController', ['$scope', 'notify', function($scope, notify){
$scope.getFn = function() {
notify.sampleFun();
}
}]);
myModule.factory('notify',
function(notifytwo) {
return {
sampleFun: function() {
notifytwo.sampleFunTwo();
},
};
}
);
var myModuleTwo= angular.module('MyServiceModuleTwo',[]);
myModule.factory('notifytwo',
function() {
return {
sampleFunTwo: function() {
alert('From notify two');
}
};
}
);
The notify factory is able to call the factory notifyTwo because notifyTwo is being injected when creating the instance of notify:
myModule.factory('notify',
function(notifytwo) //RIGHT HERE IS WHERE IT'S INJECTED
when I use a service function to define a service in angularjs, can I return a object like the following code
angular.module('myApp').service('mySerivce',function(){
return {
add: function(){};
};
});
I cannot find any document about this programming style.
Make sure you understand the syntax of factory and service
factory:
angular.module('myApp').factory('myFactory',function(){
return {
add: function(){};
};
});
service:
angular.module('myApp').service('myService',function(){
this.add = function () {};
});
I recommend that you read the following Angular style guide.
https://github.com/johnpapa/angular-styleguide
Adding some more detail here (excerpt from style guide)
Services are instantiated with the new keyword, use this for public methods and variables. Since these are so similar to factories, use a factory instead for consistency.
Note: All Angular services are singletons. This means that there is only one instance of a given service per injector.
// service
angular
.module('app')
.service('logger', logger);
function logger() {
this.logError = function(msg) {
/* */
};
}
// factory
angular
.module('app')
.factory('logger', logger);
function logger() {
return {
logError: function(msg) {
/* */
}
};
}
// factory
angular
.module('app')
.factory('logger', logger);
function logger() {
return {
logError: function(msg) {
/* */
}
};
}
In angular services are singletons, which means there is only ONE instance of that service. There are cases where you would want unique instances of objects. This is where the Factory Pattern comes in handy.
https://en.wikipedia.org/wiki/Factory_method_pattern
Within angular this pattern can most easily be seen with the $resource factory. With the $resource factory you request a unique instance of a resource.
In Angular services are classes. They are constructor functions. But only one instance is ever newed up. So a factory allows you to new instances as needed.
// my service
function Foo(fooId) {
this.id = fooId;
}
function fooFactory() {
return function(id) {
return new Foo(id);
}
}
angular.module('app').factory('foo', fooFactory);
So in the above if we delete the factory and just bind Foo to the DI container with angular.module('app').service('foo', Foo) -- what will happen? Every instance of Foo will have the same id. But with this factory, we can set the id when we create the instance.
So why use the factory and not just new up the instance by myself? Testability. Your code is not testable if you new up your classes (yes a constructor is just a class, in a sense) in your services or controllers.
Do you need this? Probably not for much.
You should just use services.
function Bar($http, $timeout) {
this.$http = $http;
this.$timeout = $timeout;
}
Bar.prototype.doSomething = function(value) {
return this.$http.get('/api/dosomthing', {value: value});
}
angular.module('app').service('bar', Bar);
What is the way to create private methods in an AngularJS controllers?
I have currently done it like this, but I wonder whether it is the correct/preferable way:
app.controller('MyController', function($scope){
myPrivateFunction();
anotherPrivateFunction();
...
$scope.someScopeMethod = function(){
...
anotherPrivateFunction();
...
};
$scope.anotherScopeMethod = function(){
...
myPrivateFunction();
...
};
...
function myPrivateFunction(){
//
}
function anotherPrivateFunction(){
//
}
});
This is correct. Your functions will only be visible inside the scope of your controller constructor function. This is the same for factories and vanilla js where functions declared in functions will only be visible in their parent function context.
In factories it would looks like as below:
.factory('my-factory', function(){
function privareMethodA() {
}
var anotherPrivateMethod = function() {
}
return {
publicMethodA = function() {
},
publicMethodB = function() {
}
};
});
So after you inject your factory into another factory or a controller publicMethodA() and publicMethodB() will be available, but privateMethodA() and anotherPrivatemethod() won't be accessible from outside of this factory.
Accessibility of controllers are similar to your snippet.
So I have a directive that takes in data objects as an argument into the scope. The problem is that I handle all my data in my service layer.
So this is some normal non-directive code:
angular.module('app').factory('appFactory', ['appValues', function(appValues) {
var getStuff = function() { return appValues.stuff; };
}]);
But if want to reuse the factory inside a directive and get appValues as an argument:
angular.module('app').directive('myDir', [function() {
return {
...
scope: {
values: '='
}
....
};
}]);
But this puts it on the scope and not into my data layer. So now I need to send the values object to every function call in my directive factory:
angular.module('app').factory('myDirFactory', [function() {
var getStuff = function(values) { return values.stuff; };
}]);
Is there any good pattern to solve this and keep data in the data-layer and bypass the scope/controller?
Also, the factory will be a singleton shared amongst instances of the directive? How should I solve that then? Create a new injector somehow? Submit to putting lots of data object logic into the controller (which I've been thought not to do)?
It was a while ago, and I guess that a simple soultion is simply to provide an function initialize(value) {... return {...};} and then the returned object has access to the value argument without providing it as a parameter everywhere:
angular.module('myDir').factory('myDirFactory', [function() {
var initialize = function(values) {
var getStuff = function() {
return values;
};
return {
getStuff: getstuff;
};
};
return {
initialize: initialize
};
}]);