Reputation: 412
When dynamically creating an element of type select
, there are two problems when setting the onclick method:
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.
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.
Upvotes: 2
Views: 98
Reputation: 25351
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.
Upvotes: 2
Reputation: 33726
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:
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);
}
this
.selElem.dataset.articleIndex = this.articleIndex; selElem.addEventListener('click', function() { updateInput(this.dataset.articleIndex); // Here you can get that value. });
Upvotes: 1
Reputation: 370739
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)
Upvotes: 2