I'm using the emit function in AngularJS and was wondering if it's possible to pass in a function as an argument.
Parent Controller:
$scope.$on("getChildFunction", function(event, func) {
console.log("function is...", func);
})
Child Controller:
$scope.$emit("getChildFunction", $scope.load_function());
However, when I use the web inspector func isn't returning at all. Are functions able to be passed up to the parent scope using emit?
If you want to pass the function itself, omit the parenthesis:
$scope.$emit("getChildFunction", $scope.load_function);
If you include the parenthesis - you'll execute the function and pass the result of the function.
Related
I have been trying to access the cloneN.querySelector('.defaultDBIcon') element(div element) inside a function makeD. I want to send two parameters for the function. Any idea how should I access this function?
cloneN.querySelector('.def').addEventListener("click",makeD(response,this));
You need to provide a function, it will receive the event target as its context when it's called.
cloneN.querySelector('.def').addEventListener("click", function() {
return makeD(response, this);
});
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.
I have a function that I would like to emit as an argument.
I have tried the following:
$scope.$watchGroup(['watch1', 'watch2'], function(newValues, oldValues, scope) {
if (scope.1 && scope.2) {
$scope.$emit('enableButton', {$scope.submit(true)});
}
});
Where $scope.submit(true) is a function I have defined in the current controller.
Then in my other controller:
$scope.$on('enableButton', function(event, data) {
$scope.buttonAction = data;
});
When I try to assign $scope.buttonAction the function that was passed through as an argument, the function just automatically fires when the $emit occurs. Why does this happen?
Because you are passing a function call with an argument and params, the function call is executed the moment you try to pass it in the event. You should pass a reference to the function instead.
$scope.$emit('enableButton', $scope.submit);
If you need to preserve the argument, you can wrap your function call in an anonymous function and pass that function. This is different than passing by reference and is often used for callback arguments:
$scope.$emit('enableButton', function() { return $scope.submit(true); });
The caveat here is that if you use a variable to represent true and that variable changes before $scope.buttonAction is called, the value passed will also change.
You can work around this in a modern browser by using .bind() to preserve the context of your variable.
$scope.$emit('enableButton', $scope.submit.bind(this, isSubmittable));
I'm trying to call a scope function from within a controller (which may or may not exist) from a directive. Calling fn() by itself, doesn't work because the fn() may not exist.
I've used scope.$apply('fn') which works, however I need to pass in parameters into the function, such as scope.$apply('fn(one, two)'); - this does not work.
Any suggestions how to call a function with parameters in a directive, that doesn't break if the controller has not yet defined the function?
Thanks!
Just call your function from a function like this :
scope.$apply(function(){
fn(one, two);
});
I don't understand what view("") does in the following javascript method that is part of Model object:
addView: function(view) {
this.views.push(view);
view("");
}
view(object) method is not defined anywhere...
view(object) method is not defined anywhere
The function that view is referring to is passed as argument to addView. This is also called a callback. A callback is a function (A) that is passed to another function (B) and is supposed to be called by that function (B).
So somewhere, there might be code that looks like
obj.addView(function(v) {
// using anonymous function expressions is a pretty common way to define
// callbacks
});
or
function someFunctionName(v) {
// any function will do, no matter how it is defined
}
obj.addView(someFunctionName);
Functions are first class objects in JavaScript and can be passed around like any other values.
It looks like it's passing in a function called view. Then it calls the view function.
Functions are first class citizens in JavaScript and can be passed as parameters to other functions.
addView: function(view) {//view is a function itself that is passed into the current function.
this.views.push(view);
view("");
}
The call could be like this
someObj.addView(function(par1){alert("I am a function too")});
Assume you have function view , if you call the view function without passing parameter in view(), then it returns like undefined, In such case we need to initialise the passing parameter value from function view("")
function view(passedData){
alert (passedData);
}