Emitting a function as an argument - javascript

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));

Related

How can you pass a function as an argument in AngularJS Emit?

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.

onclick assigned function with parameters

I'm not sure if this has been asked before because I don't know what it's called.
But why wouldn't a method like this work? Below is just a general example
<script>
document.getElementById('main_div').onclick=clickie(argument1,argument2);
function clickie(parameter1,parameter2){
//code here
}
</script>
The code above would work fine if the event handler was assigned without parameters, but with parameters, it doesn't work. I think I read online that to overcome this problem, you could use closures. I'm assuming it's because of the parentheses ( ) that is calling the function immediately instead of assigning it to the event?
Because you're calling the function immediately and returning the result, not referencing it.
When adding the parenthesis you call the function and pass the result back to onclick
document.getElementById('main_div').onclick = clickie(); // returns undefined
so it's actually equal to writing
document.getElementById('main_div').onclick = undefined;
which is not what you want, you want
document.getElementById('main_div').onclick = clickie;
but then you can't pass arguments, so to do that you could use an anonymous function as well
document.getElementById('main_div').onclick = function() {
clickie(argument1,argument2);
}
or use bind
document.getElementById('main_div').onclick = yourFunc.bind(this, [argument1, argument2]);
It is however generally better to use addEventListener to attach event listeners, but the same principle applies, it's either (without arguments)
document.getElementById('main_div').addEventListener('click', clickie, false);
or bind or the anonymous function to pass arguments etc.
document.getElementById('main_div').addEventListener('click', function() {
clickie(argument1,argument2);
}, false);
The easiest way is:
yourElement.onclick = yourFunc.bind(this, [arg1, arg2]);
function yourFunc (args, event) {
// here you can work with you array of the arguments 'args'
}
When you say onClick = function() {...} you are registering your function with some internal JavaScript library. So when the "click" happens, that library invokes your function.
Now imagine you're the author of that library and someone registered their function with it. How would you know how many parameters to pass to the function? How would you know know what kind of parameters to pass in?
clickie(argument1,argument2)
This means to invoke the function and return its return value.
clickie
This simply is a reference to the function (doesn't invoke/execute it)
To bind an event to a element, you need to use either the attachEvent or addEventListener method. For example.
/* Non IE*/
document.getElementById('main_div').addEventListener('click', function () {}, false);
/* IE */
document.getElementById('main_div').attachEvent('onclick', function () {});
A function name followed by parentheses is interpreted as a function call or the start of a function declaration. The a onclick property needs to be set to a function object. A function declaration is a statement, and is not itself a function. It doesn't return a reference to the function. Instead it has the side effect of creating a variable in the global scope that refers to a new function object.
function clickie(param) { return true; }
creates a global variable named clickie that refers to a function object. One could then assign that object as an event handler like so: element.onclick = clickie;. An anonymous function declaration (often confused with a closure; for the difference see Closure vs Anonymous function (difference?)) does return a function object and can be assigned to a property as an event handler, as follows:
element.onclick = function(event) { return true; };
But this doesn't work:
element.onclick = function clickie(event) { return true;};
Why? Because function clickie(event) { return true;} is a statement, not a function. It doesn't return anything. So there is nothing to be assigned to the onclick property. Hope this helps.

Javascript syntax confusion [beginner]?

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);
}

javascript event listener with param

I have a simple event listener:
function listen(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
var r = elem.attachEvent("on"+evnt, func);
return r;
}
return false;
}
I want to set listeners with a parameter. (the parameter is not set by the event, it is part of specific listener.
What I do and seems to work is:
function setlistener (param){
listen ('custom event', document,
function (e){
run_func_with_param(param);
}
);
}
But I dont understand if its correct because param is not supposed to be defined when the event is fired.
My question is - is it the right way to have run_func_with_param called, each time with the params that was set for it in setlistener? In other words, is param remembered and will be set to the right values when run_func_with_param will be called as result of an event? (there will be multiple listeners with different params for the same event).
Notes: No jQuery/other libraries please.
I'm using a custom event in this case.
When you use an anonymous function, the arguments and local variables from the parent scope are still available in the anonymous function.
Thus, your argument named param is available inside your anonymous function that is passed to listen(). It isn't passed to that function - it's just available directly from the parent scope.
Here's your function with some annotation in comments:
function setlistener (param){
// param is available here as an argument to setlistener
// as a normal function argument
listen ('custom event', document, function (e) {
// param is still available here directly from the parent scope
// in this anonymous function.
// This is one advantage of using anonymous functions.
if (e.data.back_button==false){
run_func_with_param(param);
}
});
}

onclick call with params

I've got a function, like this:
menu[0].onclick = function() {
filters.reset_all();
clients.get();
}
So it's called when user clicks on the first menu element. Now I need to call it form the other place and what I've done is this:
if (li.onclick) { //li and menu[0] above are the same
li.onclick.call();
}
and it works well.
But now I need to pass some params to onclick function. I've tried this .call(some_param); but arguments array in onclick is empty.
What am I doing wrong?
edit: changed into this:
menu[0].onclick = function(arg) {
console.log(arg);
filters.reset_all();
clients.get();
}
and
li.onclick.call(li,param);
still nothing
The first argument to .call() is the value for the this pointer. The 2nd, 3rd, etc... arguments get passed to the function. You only need to use .call() if you're explicitly trying to set the this pointer. Otherwise, you can just directly call the function li.onclick().
Event handlers are generally called by the system and when that happens, they are passed the event object as the first argument. If you want a function available that takes different arguments, you should create your own function for that and not use the event handling function. Your event handler can also call this other function if desired.
menu[0].onclick = function() {
myFunc("aaa");
}
function myFunc(arg1) {
// do whatever here
filters.reset_all();
clients.get();
}
if (li.onclick) {
myFunc("bbb");
}
it should be
call(object, param1, param2, param3...);
In your case you can write
li.onclick.call(li, param1);
The first parameter of call() is the context (in this case this) the rest of the parameters go into the arguments array in order. If you use apply() instead of call then you have just two parameters: apply(this, arguments_array)

Categories

Resources