How To Make This Refer To My Clicked Object Javascript - javascript

button.setAttribute("onClick" , "addToCart()");
I wrote this line in creation of an element to do an action, but when i click it and deal with "this" it refers to window not the object
How can i fix this to make the click refer to my element in order to get some data from the parent ?

Don't use setAttribute for event handling. Use addEventListeners instead. For now, you could make your function like this, which uses event object that gets passed when it's called on the triggering of the event, in this case click
function addToCart(e){
var that = e.target; // use that instead of this
// more code goes here
}
And then you could just set it to the onclick property
button.onclick = addToCart; // pass the function reference

Related

How to remove event listener from anonymous function without naming it?

I need to remove event listener from a function.
I've searched here and google but all solutions I found were about make a reference or give name to each function created, but my function is created within a loop so it doesn't work:
for(let i = 0; i < boxSelected.length; i++){
boxSelected[i].addEventListener("click", function(){
// my code here
Is there a way to add the event listener to each element created inside loop and distinguish between them later?
or
Can I remove the event listener without need to name it?
removeEventListener requires you pass reference to function not its name.
So once you save function itself into any variable(say, array or object with linking to index) you will be able to remove it later.
Also you can put single listener on common parent node and disable/enable processing for specific elements by changing some their attribute

Function parameter evaluates to undefined

When dynamically creating an element of type select, there are two problems when setting the onclick method:
It is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
This results in a final HTML tag where no onclick is shown at all.
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
However the functionality seems to be broken, as the argument always evaluates to undefined
Here a simple example of my problems:
var selectElem = document.createElement("select");
selElem.id="articleSelector_"+this.articleIndex;
console.log("the index of the article is " + this.articleIndex);
selElem.setAttribute("onclick","updateInput(this.articleIndex);");
//selElem.onclick="updateInput(this.articleIndex)"; //this does not work
The log shows the correct number. Inside the updateInput method, the argument is of value undefined instead of the number previously shown in the log.
Try attaching handlers with pure Javascript, and not with HTML, without onclick = "... (which is as bad as eval).
The this in your script refers to the calling context of the function - what is it?
You might want:
element.addEventListener('click', () => {
updateInput(this.articleIndex);
});
(arrow functions retain the this of their surrounding scope)
it is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
What that code does is it assigns the string "updateInput(this.articleIndex)" to the onclick which makes no sense and certainly not what you want.
Even if you remove the quotes:
element.onclick = updateInput(this.articleIndex);
It is still incorrect because it assigns the result of the updateInput() function to the onclick which is again not what you want.
You need to assign a function name to the onclick like this:
element.onclick = updateInput;
However, this doesn't allow you to pass a parameter as you wish. To do so, you need to use an anonymous function:
element.onclick = function() {
updateInput(this.articleIndex)
};
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
This works because it sets the attribute onclick and it is a string type, so everything is correct. It is equivalent to using the anonymous function above. The only difference is this, which in this case refers to the element itself, while in the above code it depends on the context that the code appears in. That's why in this case the argument always evaluates to undefined because the select element doesn't have an articleIndex property.
The problem is the value of the context this when that element is clicked, the context this is not available anymore at that moment.
You have two ways to solve this problem:
You can use the function addEventListener to bind the event click, and bind the function/handler with the desired context this:
The function bind binds a specific context to a function.
selElem.addEventListener('click', updateInput.bind(this));
function updateInput() {
console.log(this.articleIndex);
}
As you need a specific value, you can use data attributes. That way, you don't need to worry about the context this.
selElem.dataset.articleIndex = this.articleIndex;
selElem.addEventListener('click', function() {
updateInput(this.dataset.articleIndex); // Here you can get that value.
});

Pass paramtes to event function

I bulid a function to event and I want to know how can I pass parameters to that function?
I use addEventListener method to add events
What I need is to pass the element variable to the function mean this object
For example if I use attribute method to add event I do like this:
<div onclick="function(this)">
And then the function will get the div element
Now my question is how can I pass the this object to the function when I use addEventListener
Is there anyway to get this thing?
Blah.addEventListener(function(event){
var element = event.target;
});
Posted from phone. Please forgive
http://www.w3schools.com/jsref/met_document_addeventlistener.asp
Define your listener with a parameter, this will be an event object.
In this object you will find the triggered element.
In an event handler, such as onclick, 'this' will automatically point to the element, where the event is triggered. You can use it inside your anonymous function.
Note: It's not a string but a HtmlElement.
Hope I have understood your question correctly.

Computed binding doesn't work with on-click (Polymer)

<template is="dom-repeat" items="{{myItems}}">
<div on-click="{{ComputedBindingFunction(item)}}">Foo</div>
</template>
This yields an error saying:
listener method {{ComputedBindingFunction(item)}} not defined
Shouldn't the function be executed, instead of literally trying to attach the function name with {{}}'s to on-click according to the docs?
Note that ComputedBindingFunction returns a function.
The example shown in the documentation you link to isn't for calling methods or firing events, it's for using computed bindings.
i.e.
<div>{{ComputedBindingFunction(item)}}</div>
If you're your trying to trigger an event, remove the braces:
<div on-click="ComputedBindingFunction"></div>
...
Access item from the triggered event
ComputedBindingFunction: function(event){
_ComputedBindingFunction(event.model.item)
}
Firstly, Attributes for event listeners (e.g., on-click, on-tap, etc) don't allow computed bindings as an argument, only a string.
Secondly, even if they did, which would be super cool in the future, your example still wouldn't work because you are returning a function from the computed binding and not a string.
Your computedFunction should instead be returning the name of the function you want to call which is defined using the arguments supplied when the event is fired.
Example:
html polymer event handler attribute
<div on-click="{{computeFunction(a, b}}">Button</div>
computeFunction makes a new function "add" and returns the name of this function as a string.
computeFunction: function(a, b) {
functionName = "add";
this[functionName] = function() {
// Does whatever you want with arguments, a, b
// Like maybe adding them together.
return a + b
}
return functionName;
}
add: function(a, b) {
return a + b;
}
This way the function called "add" which is called when the on-click event occurs would always be using the new variables "a" and "b" assigned to it.
Until this is available, which it might be never, You can store parameters in an attribute on the element which fires the event.
<div on-click="someFunction" someFunction="{{item}}">Button</div>
someFunction: function(e) {
// Current target is the node that fired the event,
// It has our stored parameter "{{item}}" as a value of "someFunction"
var item = e.currentTarget.getAttribute('someFunction');
// Do something with item
console.log(item);
}
As you can see I stored the item in an attribute with the name of the function called by the on-click event.
This way it's easy to tell what arguments are going to be passed to the function just from looking at the html, and works for multiple event handlers on the same element.

jQuery: adding change event handler with predefined function

So I have the following:
var change_handler = function(element) {
// ... do some fancy stuff ...
}
Now, I want to attach this to an element. Which is the better/best or more correct method?
$('element_selector').change(change_handler(this));
Or...
$('element_selector').change(function() { change_handler(this); });
And does it make any difference if you're passing the object to the function or not?
Neither..
$('element_selector').change(change_handler);
change_handler will be the so to speak pointer to the method and the argument of the element is already passed by jQuery
If you were to use $('element_selector').change(change_handler(this)); it wouldn't actually assign the method as the handler but rather run the method and attempt to assign the result as the handler, the other option is superfluous because you can use the method name as described above instead of re-wrapping the method.
This is another way to approach the problem given by the OP... partial function application a la another SO Q. Bind the change handler with the arg of interest and pass the resulting partial as the arg to the change handler:
var myChangeHandler = partial(change_handler, this);
$('element_selector').change(myChangeHandler);

Categories