Setter functions in angular providers - javascript

From my understanding factories are an abstraction over Angular's providers, which allow you to return data with less lines of code. However, providers provide more flexibility in that you can better define the service's functionality. I'm still really confused on how to call a simple function from a provider. Everyone seems to be doing them differently and I cannot get mine to work:
myApp.provider('myProvider', function() {
myVar = true;
$get: function() {
return {
myVar: myVar,
}
},
toggleFalse = function() {
myVar = false;
},
})
myApp.controller('myController', function($scope, myProvider) {
myProvider.toggleFalse();
});
This does not seem to work - and I'm having trouble understanding services in general. It says toggleFalse is not defined. How do you properly define a setter function on an Angular service that can be controlled through a controller?

If you do console.dir(myProvider), you'll see that you are getting the object returned from $get. You need to put the function on the returned object:
$get: function() {
return {
myVar: myVar,
toggleFalse: function() {
myVar = false;
},
}
},

This is a simple question of closure.
If you want every instance to have a unique everything, then store everything inside $get.
If you want the majority of the object to be unique, but have some methods or objects/arrays that every instance shares with each other, then define those in the function closure outside of $get and append them to the object returned from $get.
... ("myProvider", function () {
var sharedValue = 19,
sharedFunction = function () {
sharedValue += 1;
return shared value;
};
return {
$get : function () {
return {
unique : 1,
shared : sharedFunction
};
}
};
This isn't an Angular issue, so much as a core piece of JS's behaviour, which happens to be inside of an Angular paradigm.

Related

What is the meaning of enforce parameter in AngularJS Factory

I was going through the details of how angular actually creates factory just by using module.factory() method.
I found that internally angular uses following method which internally uses provider only
function factory(name, factoryFn, enforce)
So my question is regarding the third parameter enforce of this function ,what it actually does.
When creating an Angular service or factory, behind the scenes, Angular eventually uses the same function for both:
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
When creating a service, a return value is generally not sent, and behind the scenes, Object.create() is called to create an object containing the sayHello method.
app.service('MyService', function () {
this.sayHello = function () {
console.log('hello');
};
});
However, when creating a factory, an object literal is returned:
app.factory('MyService', function () {
return {
sayHello: function () {
console.log('hello');
};
}
});
Basically, enforce is used to enforce a return value. It's not just a question of "Is this a service or factory?" since you can still return an object literal from a service if you wanted to:
app.service('MyService', function () {
return {
sayHello: function () {
console.log('hello');
};
}
});
Regarding the question: "Which should you use?" check out this:
http://blog.thoughtram.io/angular/2015/07/07/service-vs-factory-once-and-for-all.html

How to call a factory method dynamically coming from variable?

I have a service which will return the name of factory. I already injected all the factories into controller. I need to use the variable to call the method inside that factory. I know i can use
if(var == 'factoryname') {
factoryname.method()
}
but i don't want those if conditions because i have number of factories. Is there any way to call a method inside that factory like in java script
window[var]
You should consider storing all of your factories on an object:
var factories = {
factoryA: { method: function() {} },
factoryB: { method: function() {} },
};
var factory = 'factoryA';
factories[factory].method();

Can I avoid using the word "this" inside Typescript when calling a function that came in through a constructor?

I have:
class AdminHomeController {
private config1; // I tried different variations here but none worked
public config2; //
constructor(
private $scope: IAdminHomeControllerScope
) {
this.config = $scope.config; // << this works
}
static $inject = [
'$scope'
];
configChanged = (clear) => {
this.config.clear();
};
}
This code works and this.config has all the methods I need. However is there a way
that I can remove the need for the this? What I would like to be able to do is to code the following:
configChanged = (clear) => {
config.clear();
};
I tried with many different variations but I cannot get it to work.
Here's an example of the same code before changing to Typescript:
angular.module('admin')
.controller('AdminHomeController', [
'$http',
'$q',
'$scope',
'utilityService',
adminHomeController]);
function adminHomeController(
$http,
$q,
$scope,
utilityService
) {
var app = $scope.app;
var config = app.config;
var home = this;
var util = utilityService;
home.autoSave = false;
home.data = {};
home.entityType = null;
home.forms = { grid: null, modal: null };
home.grid = { view: [], data: [] };
home.modal = { visible: false };
home.row = {};
home.rowSelected = null;
home.configChanged = function (clear) {
config.put();
if (clear) {
home.grid.backup = [];
home.grid.data = [];
}
};
As djechilin said:
If you omit "this," the interpreter will simply look for the variable name in local, closured and global scopes, not actually look up object properties
So you can potentially do that in TypeScript by moving the function definition into the body of the constructor (where you have access to the closured $scope variable). Here we also close over config and then use it in the function:
class AdminHomeController {
configChanged: ()=>void; // Need to declare the function
constructor(private $scope: any) {
var config = $scope.config;
this.configChanged = ()=> { // And then assign it
config.clear();
};
}
}
As you can see, it's not elegant. You have function definition + declaration split. Also, the constructor body is becoming needlessly heavy.
TypeScript is not to blame here. It's just JavaScript.
In Javascript definitely not, and in Typescript I'm pretty sure no. References in Javascript bind lexically, not whatever the other way is called. If you omit "this," the interpreter will simply look for the variable name in local, closured and global scopes, not actually look up object properties. You would need some sort of magical flag to say "this variable is an object property," and the way this is implemented is with "this."
This is very usual in Javascript. Compiled languages like Java don't suffer this problem, and I'm not sure about other dynamic languages. It's not necessarily hard to solve; it's just not how JS has done things (arguably wrongly).

JavaScript convention: How do you assign arguments to the parent scope

var problemtest = function () {
var parameters;
return function (parameters) {
parameters = parameters;
}
}
var mysolutiontest = function () {
var parameters;
return function (parametersIn) {
parameters = parametersIn;
}
}
This is more of a JavaScript convention question.
Usually I have code similar to that on top. A function take arguments and assigns it to parent scope. However, I cannot use it as in problemtest, as the parameters that are arguments hide the parameters from problemtest.
In OO Programming we can use this, but in JavaScript I cannot use this, so I usually implement a solution similar to mysolutiontest. However, I am not fully satisfied with this solution. Is there a better way of doing this?
If your functions need to share some properties, then assigning them to an object is an elegant and common pattern:
var object = {
property: ['item'],
methodOne: function() {
console.log(this.property);
},
methodTwo: function() {
console.log(this.property);
}
};
object.methodOne(); // ['item']
object.methodTwo(); // ['item']
For further information on how 'this' works within an object - http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/
I usually use _parameters as a convention. This stems from my Java past. This isn't isolated to your example or to Javascript. Any language that does not force you to qualify the variables of any enclosing scope would lead you to the same problem.
var mysolutiontest = function () {
var _parameters;
return function (parameters) {
_parameters = parameters;
}
}
I've also seen people use p_parameters to quality function argument names. This is not one of my favorites tho.
var mysolutiontest = function () {
var parameters;
return function (p_parameters) {
parameters = p_parameters;
}
}
My 2c.

javascript organisation

I came across this Q/A on javascript code organisation.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Currently I do this,
var DED = new Object;
DED = {
sidebar : {
method_1 : function (data){
//some stuff
},
method_2 : function(data){
//do more
}
},
main : {
//.......
},
globalVariables : {
//...
}
}
What is the advantage of one over the other?
Warning: newbie here.
As indicated, that method uses closures to implement private functions and data. It's an alternative to the constructor method (below). E.g.
var DED = new (function()
{
var private_var;
function private_method()
{
// do stuff here
}
this.method_1 = function()
{
// do stuff here
};
this.method_2 = function()
{
// do stuff here
};
})();
With the DED method shown in your question, there is no constructor. Rather the function returns an object created from an object literal. The functions in that object have the private variable and method closed into them.
What you return from the anonymous self-calling function (function(){})() is the interface you publish for your "module" (DED).
DED.method_1() is public. private_method/private_var are not accessible from outside but everything inside of your self-calling function has access to them.
If you like this kind of access-control this is a good way to prevent other developer from accidentally messing with the internals of your module. In a lot of cases i'd just go for a naming convention like a leading underscore to indicate internals.
Javascript is very dynamic and if someone really wants to mess with code they have no write-access to they will be able to do so. Edit: This turns out to be a wrong assuption and not the case for private data in constructors or closures. Please, see: http://www.crockford.com/javascript/private.html

Categories

Resources