Parameters in javascriptmethods - javascript

I haven't understand the function definition inside a method in javascript.
For example in AngularJS I have th code:
sth.controller('ctrlname', function ($scope, $ionicModal, par3, par4){
//code
});
I also have th code:
var f = function (par5,par6){
return par5 + par6;
}
If I call f(2,3) I get the result 5.
So in controller and other similar examples I choose arbitrary names for the parameters inside function or variables that exists previously?

As #MikeFeltman said, you can use any name for your functions' arguments
BUT
Angular as its own logic for dependency injection and it can use argument's name to identify which piece of software your controller/service/etc depends on.
Let's create a B controller that depends on a A service:
angular.module("testModule",[])
.service("A",function(){
//do stuff
})
.controller("B",function(A){
//do other stuff
});
Angular injector, will look at the B constructor's arguments (here A) and try to find the expected service.
But you can name your arguments as you want :
angular.module("testModule",[])
.service("A",function(){
//do stuff
})
.controller("B",["A",function(dontCareAboutVarName){
//do other stuff
}]);
Here the injector, won't look at the function's arguments as it will find an array describing the dependencies and, the last item will be the controller constructor.
Please, take a look at the documentation about angular's injector

The parameters are new variables from within the functions, regardless of it they exist already or not, but I would not use the same names as variables that are available from the containing function in order to avoid confusion. I'd recommend reading up on closures in JavaScript to get a better understanding of this. This is a pretty decent read on them: http://javascriptissexy.com/understand-javascript-closures-with-ease/.

You can define a function in controller like this ..
sth.controller('ctrlname', function ($scope, $ionicModal, par3, par4){
//function...
$scope.sum = function(par3,par4){
return par3 + par4 ;
}
});

Related

In Angular 1.x When "watching" in a directive; why does watching a function that returns a variable act different than just watching the variable?

The easiest way to explain this question is with some sample code so here is a very simple directive written in ES6 syntax:
export default class IsFoo {
constructor() {
// Set the directive properties
this.restrict = 'A';
this.require = 'ngModel';
}
link(scope, element, attributes, controller) {
let foo = scope.$eval(attributes.foo);
controller.$validators.isFooBar = (modelValue) => {
// make sure we have the most recent value foo
foo = attributes.foo;
return foo === 'bar';
};
scope.$watch(() => {return attributes.foo;}, () => controller.$validate());
}
static directiveFactory() {
IsFoo.instance = new IsFoo();
return IsFoo.instance;
}
}
IsFoo.directiveName = 'isFooBar';
That is a rough version of my directive with all the actual important validation removed.. it's pretty simple.
If I change the watch line to be:
scope.$watch(attributes.foo), ()=>controller.$validate());
It doesn't work. Why? Why does the function returning the attributes.foo work?
What is the difference that causes the end result to be different?
Also, disclaimer, I'm intentionally not using scope isolation because the directive is being used on an element that has another directive that uses scope isolation.. so they collide and you get an error Multiple directives asking for new/isolated scope on: xxx.
My rough guess is that it is related to how closures behave in javascript but I can't wrap my head around how the two behaving differently.
Thanks for any insight you can provide.
The interface for scope.$watch is according to the documentation the following:
$watch(watchExpression, listener, [objectEquality]);
With watchExpression being either a string or a function. If it is a string, it is interpreted as a path within your scope object. Assuming attributes.foo is "test.something", it will watch scope.test.something - if it exists.
If you want to watch for changes of the value of attributes.foo, you have to use the function, or attach attributes.foo to your scope and passing "attributes.foo" as watchExpression.

How does angular's controller method make $scope available to my function argument

I am looking for a pseudo code answer, or conceptual answer please.
After programming for a number of years I have never created a class method that receives a function argument such that the caller of the method automatically gets access to 'invisible' properties.
If I try to access $scope outside of my my_app.controller(...) method, I get an error so I know it's not global; if I try to access it from my_app.$scope or angular.$scope I get undefined.
So how does my function parameter get access to it:
my_app.controller('my_controller' , function( $scope , ... ) { ... }
UPDATE (as I am learning):
// javascript
var my_class = function( argument_A )
{ this.some_prop = argument_A ;
this.some_method = function( argument_B )
{ console.log( argument_B ) ; // function(boo)
} ;
} ;
var my_instance = new my_class( "my_string" ) ;
var my_function_argument = function( boo ){ } ;
my_instance.some_method( my_function_argument ) ;
Functions Are First Class Citizens
In JavaScript and other modern languages (Scala, Haskell, LISP, etc.), functions are treated as first-class citizens. Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures. Some programming language theorists require support for anonymous functions (function literals) as well. In languages with first-class functions, the names of functions do not have any special status; they are treated like ordinary variables with a function type.1
The above example can be re-factored as:
var myController = function ($scope, ... ) {
console.log($scope);
$scope.message = "Hello world"
};
my_app.controller('my_controller' , myController );
In this case the .controller method stores the myController object in the cache of the AngularJS $controllerProvider service. I.e. cache["my_controller"] = myController;
Later when the $compile service encounters a directive that needs a controller:
<div ng-controller="my_controller">
{{message}}
</div>
The $compile service creates a new scope, retrieves the myController function from the $controller service cache, and invokes the function with the new scope as the first argument of the function.
The $compile service also creates a $watch listening function that tracks the $scope.message variable. On each digest cycle, if $scope.message has changed, the DOM is updated appropriately.
In the examples from the question:
//These are function invocations, the variable must be defined
console.log( boo ) ; // ERROR: boo is not defined
my_instance.some_method( boo ) ; // ERROR: boo is not defined
The last form uses an anonymous function literal (or function expression). The anonymous function is an object passed as an argument to the method named .some_method.
//The anonymous function is an object passed as an argument
//boo is a parameter to be supplied when the function is invoked
my_instance.some_method( function( boo ) { } ) ; // NO ERROR
For more information on function literals, see MDN JavaScript Reference -- function expression.
Dependency Injection and Connecting Arguments by Name
Normally in JavaScript, function arguments are connected by position. In the AngularJS framework, function arguments are injected by name. How is that done?
From the Docs:
Inference
In JavaScript calling toString() on a function returns the function definition. The definition can then be parsed and the function arguments can be extracted.
-- AngularJS $injector Service API Reference -- Inference
So in the example:
my_app.controller('my_controller' , function( $scope , ... ) { ... }
The $injector service does a toString() on the controller construction function and parses it. The service detects that $scope is the first argument of the function and uses that knowledge to invoke the function correctly.
You can see fn.toString() being used here in the source code.
While you are creating a function and passing dependency name inside function parameter, in that case angular creates an object for each dependency by resolving that dependency from its DI container. This kind of dependency injection technique known as constructor function(there are two more DI techniques).
When you inject controller on DOM using ng-controller directive at that time function is passed to $controllerProvider's register function. controller function is known as factory function. Which will get passed with dependency as parameter. $injector service get each of dependency from function, and do $injector.get to return out what ever dependency is registered in DI container. While doing returning $scope dependency it creates out new scope from rootScope using $rootScope.$new(isolate, parent) method. $new method takes two parameter 1st one as bool & 2nd one as parentScope parameter. Other dependency directly taken out from register component to module.

Angularjs : Controller Function : variables : 'var' or controller propeties

In AngularJS application inside a function which is again inside a Controller,
what will be best approach while creating a variable.
normally create with var keyword
function getAnswer() {
//Some code here
var persistedDateValue = templateFactory.getAnswer(ctrl.item.ItemId);
//Some other code here
return persistedDateValue;
}
add it to the controller scope
function getDateAnswer() {
//Some code here
ctrl.persistedDateValue = templateFactory.getAnswer(ctrl.item.ItemId);
//Some other code here
return ctrl.persistedDateValue;
}
Here ctrl is controller , like in Directive controllerAs: 'ctrl',.
My understating is that option one is better as we do not need this variable other then this function.
Please suggest.
I agree with ZSnake's answer, but if you do need to make this variable available in the rest of your controller on on the view then you will need
.controler('ControllerName', function() {
var _this = this;
function getDateAnswer() {
//Some code here
_this.persistedDateValue = templateFactory.getAnswer(ctrl.item.ItemId);
}
Best practice would be option 1, if, as you said, you're not going to use that variable elsewhere. That way you avoid having unused data on your scope.
Javascript is very permissive on this. If you were using a more strict language as C or any of it's variations you couldn't do what you expose in the second option.
This way of accessing variables form an outer scope (from outside the function) is called "closure" and could be helpful in some situations, but for sure not in the one you're exposing, that would only mess your code, since the function itself can return it's results by it's result stament in a "normal" fashion, maintaining one of the most important principles of the programming science: Separation of Concerns (SoC for friends)
So stick to option 1

Angular constructor in a controller

I tried this with no luck:
app.controller('PageLayoutController', function ($scope)
{
// Scope properties
$scope.PageMap = {};
// Constructor
function PageLayoutController() {
alert( "contructing" );
}
return PageLayoutController;
});
I'm looking for a default or popular way of defining the construct of these controllers in angular.
I'm aware i can just create a function called Construct and then call it first, but i wondered if there was an official way of doing it?
I assume you may want to invoke the defined function during Controller getting instantiated. If that's the requirement, you can follow the following syntax.
angular.module('myApp', [])
.controller('PageLayoutController', '$scope', function($scope) {
// Scope properties
$scope.PageMap = {};
$scope.PageLayoutController = function() {
// Do stuffs here
};
// Call the function when the Controller get first invoked
$scope.PageLayoutController();
});
Also you can listen into the $routeChangeStart event and call the function as well.
$scope.$on('$routeChangeStart', function(next, current) {
... you could trigger something here ...
});
Also you can use any of the following events as well.
$routeChangeSuccess
$routeChangeError
The controller function is already a constructor so anything you write in the its body will be executed on construction.
Not quite sure what you are exactly trying to do. But being specific, angular instantiates the controller constructor with new operator when it is needed. So what you are trying to do is more of javascript specific question than angular specific. It does it as:
new ctor(); //or new ctor;
had it been new (ctor()) your code will work, but that is not how it happens obviously. The function reference passed in is newed up, not the result of the function execution. So in your case if you were to do this then you need to return the newed up instance. i.e
return new PageLayoutController;
Example

Function inside the AngularJS Controller

I have code snippet in which there is a Angular Modular Controller, but there is a function inside the same controller and with a call, which is raising doubt in my mind that is this way of coding allowed in Javascript or Angular? If Yes then how does it read it? See the below code format I have:
obj.controller('CartController',function($scope){
$scope.totalCart = function(){
var total = 10;
return total;
}
function calculate(){
...Some Logic..
}
$scope.$watch($scope.totalCart, calculate);
)};
Please help me to understand that is this type of function definition and call within a controller allowed in Angular/Javascript?
The calculate() is a private function -- it is only accessible in the scope of CartController. If you do not need to make use of your function in the view it is good idea to make it private. It says that it is not intended to be used in the view, so if someone else will be working with this code should think twice before use it in the view. Moreover: from within calculate you have access to all objects that are accessible in the scope of the CartController (including objects passed to CartController as parameters).
Function declared in this way is a proper JS function, which means you can get reference to it by its name. Sometimes it is thought to be more readable if you declare / create your function in advance and only then assign them to properties of some other object (in this case $scope):
function someFn (...) { ... }
function someOtherFn (...) { ... }
...
$scope.someFn = someFn
In the above snippet the intentions are very clear: make someFn accessible, while keep someOtherFn private.
Btw. declaring functions like: function nameFn(...){...} is called function statement; you can very similarly do it like: var nameFn = function(...) {...} (so called function expression). There is a slight difference between those -- basically it is illegal:
someFn();
var someFn = function(...) {...}
whereas, this works:
someFn();
function someFn(...) {...}
Sometimes you are forced to use this pattern, look e.g. at my answer to this question.
$scope.launch = function (which) {
};
var _func = function () {...}
The definition is allowed, it has the same affect as
$scope.$watch($scope.totalCart, function(){..some logic...})

Categories

Resources