Javascript onclick getvalue is undefined [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
my problem has 2 sides to it.
I am trying to send a simple get value that is generated via a loop like so:
for(var x=0; x<del.length; x++) {
del[x].onclick = function () {
WORK(x);
}
}
Here is my frustrated WORK function
function WORK (x) {
var y = ids[x];
var url = "Delete.php?val=" + y;
window.location = url;
}
I know i just have to pass the value to the function...but if i set it up like that the page executes the function on load and doesn't wait for my click and as is it is now it will always pass an undefined value...what is going on here?

Variable hoisting + non-scoped variables in for loops.
Use .forEach:
Array.prototype.slice.call(del).forEach(function(elem, index) {
elem.onclick = ...
});
Or if you can't, use an immediately-invoked anonymous function:
for (var x = 0; x < del.length; x++) {
(function() {
var elem = del[x];
...
})();
}
When you iterate through the loop, there is only ever one x variable. It is not scoped to the for loop, and changes on each iteration (x++). When you trigger a click, the event handler is called, which in turn calls WORK with the value of x as an argument, which would've already been del.length by the time it runs.

Related

Looping result last index of array [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have the following code, to add each element an event using addeventlistener:
var x, y, z;
elm = elm.normalize();
if(!isobj(elm) && iselm(elm)) {
elm = new Array(elm);
}
for(x in elm) {
(function() {
elm[x].addEventListener('click', function() {
alert(x);
});
})();
}
but when I click any element that added an event by the loop it always show the last index example, like when I click the element it show an alert with example text inside the alert box.
Here was the result of console.log(elm) after elm = elm.normalize():
[sample: input.sample.fld, example: input.example.fld]
isobj(elm) is a function to check if variable is an object, same like
iselm(elm) is a function to check if variable is an element.
Due to fix this, I'm trying to use, (function() { /* I put the addEventListener as above */ })(); inside the loop, but still not work.
I already make sure that x is always showing it index, but I didn't know why it always showing the last index in the event.
Please help.
By the time that line of the code is executed, the for-loop has finished.
For explanation:https://dzone.com/articles/why-does-javascript-loop-only-use-last-value
You can use let if your browser supports it. (See article for explanation and alternatives)
var x, y, z;
elm = elm.normalize();
if(!isobj(elm) && iselm(elm)) {
elm = new Array(elm);
}
for(x in elm) {
(function() {
let myX = x;
elm[myX].addEventListener('click', function() {
alert(myX);
});
})();
}

JavaScript Why does the index of a for loop add one when adding eventlisteners [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have a question which might sound silly. In the code below there are 2 console.log(i) statements. I want to know why does the second console.log(i) statement returns value of 2 and not 1 as the former on the first iteration (i.e. 1st statement i=n, 2nd: i=n+1). Shouldn't both be equal to 1 until the end of the loop?
function toggleWrapper(){
var el1 = document.querySelectorAll('[class="tCell entryDesc"]');
for (var i = 1; i < el1.length; i++) {
console.log(i);
el1[i].addEventListener('click', function(ev){
console.log(i);
var el2=document.querySelectorAll('[class="additionalInfoContainer"]');
if (el2[i-2].clientHeight) {
el2[i-2].style.maxHeight = 0;
}
else{
el2[i-2].style.maxHeight = el2[i-2].scrollHeight +"px";
}
},
false);
}
}
The problem is that the variable i, within each of your addEventListener() functions, is bound to the same variable outside of the function. simply change your for loop to :
for (let i = 1; i < el1.length; i++)
In the loop with let based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work fine.
i think is something in your code because if you try to make a for loop with two "console.log()" it doesn't do that

Value is not being passed to for loop [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
This is a bit of a mystery for me. I have two functions:
1)
var revisionNumber;
var $list = $('<ul>');
TFS_Wit_WebApi.getClient().getWorkItem(284)
.then(function(query) {
revisionNumber = query.rev;
});
2)
for (i = 0; i < revisionNumber; i++) {
TFS_Wit_WebApi.getClient().getRevision(284, 6)
.then(function(query) {
$list.append($('<li>').text("story board" + revisionNumber));
});
}
The reivisonNumber value is supposed to be 15. When in for loop I put instead of the variable a number 15, the second function works just fine as well as for loop and it actually displays this number 15.
If I remove for loop, it also works and displays the value of revisionNumber variable from the first function.
However, when I put revisionNumber in my for loop, the second function does not work at all.
Why is it not going inside the second function with the above for loop?
The for loop is probably being executed before the getWorkItem().then() callback is being executed. You will need to wait for that callback to run before running the for loop, either by moving it into the callback function, or putting it in it's own function and calling that function in the callback.
For example:
var revisionNumber;
var $list = $('<ul>');
TFS_Wit_WebApi.getClient().getWorkItem(284).then(function (query) {
revisionNumber = query.rev;
for (i = 0; i < revisionNumber; i++) {
TFS_Wit_WebApi.getClient().getRevision(284, 6).then(function (query) {
$list.append($('<li>').text("story board" + revisionNumber));
});
}
});

Having issues preserving variable contents in closure [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
(This question is related to this and this but answers there haven't helped me figure out what's wrong in my case.)
I am trying to create an array of clickable elements where each element is bound to a separate instance of some object.
I've simplified the real code I'm working on as much as possible for this question here:
//----------
// Setup part
// SomeObject just holds a number
var SomeObject = function(number) {
this.number = number;
this.getNumber = function() {
return this.number;
};
};
// contains SomeObject(1) through SomeObject(9)
var someArrayContainingObjects = [];
for(var i=1; i<=9; i++)
{
someArrayContainingObjects.push(new SomeObject(i));
}
//----------
// Problem part
for(var y=0; y<3; y++)
{
for(var x=0; x<3; x++)
{
var obj = someArrayContainingObjects[y*3 + x]; // Creating new variable in the loop every time explicitly with var statement?
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber()); // Will always be 9
})
);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I thought by explicitly using var obj = ... inside the loop I would create a new context/scope/however it's called for each anonymous click() callback function I'm creating – so that when I click one of the objects, the appropriate number of the respective SomeObject is alert()ed and not always the number of the last SomeObject the loop takes from the array.
Could someone please explain to me why this code snippet does not work as expected, and what to change to have the code function correctly?
To create closure scope in JavaScript you need to invoke a function. In JavaScript we can also invoke functions as soon as you declare them. They are called immediately invoked function expressions
This way you can preserve your x and y values in the scope of the IIFE.
for(var y=0; y<3; y++) {
for(var x=0; x<3; x++) {
(function (x, y) {
var obj = someArrayContainingObjects[y * 3 + x]
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber())
})
)
}(x, y))
}
}
Working codepen
Also, this is a big problem that people encounter when they try to write JavaScript as if it was a class based language. I would try to look into writing JS from a more functional perspective

JavaScript: preserve a value in a for loop [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
guys, really need for your helps. I got some code block as follows:
function readyToSubmit(answerPack, answerArr, len) {
for (var i = 0; i < answerArr.length; i++) {
var questionId = answerArr[i].id;
console.log(questionId);
// below is an database async operation
userStore.getDoc(id).then(function(doc) {
// if I console.log 'answerArr[i]' here, it will be undefined
// I know it's 'cause the 'i' here is answerArr.length, so it would be undefined
// I want my questionId differently, but it is always the last one in the array
// I know it's the closure issue, but don't really know how to handle it.
doc.questionId = questionId; // always the same one
answerPack.push(doc);
});
}
}
So, how can I exactly get what I want in every round, I mean different questionId, not always the last one. Many many thanks, :)
You could so somethink like ,
function readyToSubmit(answerPack, answerArr, len) {
for (var i = 0; i < answerArr.length; i++) {
var questionId = answerArr[i].id;
doasynch(questionId);
}
}
function doasynch(questionId) {
userStore.getDoc(id).then(function (doc) {
doc.questionId = questionId;
answerPack.push(doc);
});
}
Read
How Closure works
Closure inside loop issue

Categories