0

I already read JavaScript closure inside loops – simple practical example and Why am I only getting the last item from javascript for loop? but still can't figure out, so I post my code to ask for help

function Produit(nom, prix){
    this.nom = nom;
    this.prix = prix;
}

// ______________ Objet ____________________

var apple = new Produit("apple", 0.30);
var banana = new Produit("banana", 0.03);
var pear = new Produit("pear", 0.35);
var kiwi = new Produit("kiwi", 0.40);

var produit = [apple,banana,pear,kiwi];


for (var i = 0; i < produit.length; i++) {
    $('.test').html(produit[i].nom);
};

html

<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>

The for loop only gets the last item name "kiwi" in html.
I tested the loop with console.log and alert and they both get the 4 item names: "apple","banana","pear","kiwi"

Why doesn't this show up in my HTML?

Community
  • 1
  • 1
Jiang Lan
  • 171
  • 1
  • 12
  • Your loop writes the same value to all elements matching `.test` each time. All of your iterations are overwriting the text from the previous iteration. – Babak Naffas Apr 25 '16 at 22:40
  • The divs are all the same target, because they have the same class. So the loop will write every value to the same spot (in your case in all the 4 divs). You have to give any div an ID, or you have to call the div by their position in the DOM. – John Apr 25 '16 at 22:40

5 Answers5

1

Simply change the line in your for loop to this:

$('.test').eq(i).html(produit[i].nom);
ndimatteo
  • 498
  • 5
  • 22
  • It work perfectly! I think the other answers can do it too, but yours is simple and quick, thanks a lot! – Jiang Lan Apr 25 '16 at 23:13
1

When you call $(".test").html() you're replacing the contents of all the elements with that class. You need to use .eq() to specify a particular one.

for (var i = 0; i < produit.length; i++) {
    $('.test').eq(i).html(produit[i].nom);
};

Another way to do it would be to pass a function to .html(). It receives the index of the element, and can use that to index the produit array:

$('.test').html(function(i) {
    return produit[i].nom;
});
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

The problem is you're changing the content of every single element with a test class on every loop iteration. Example:

$('.test').html('Replaced');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>

If you want to change the nth .test element on every loop iteration, you can use .eq.

var list = ['a', 'b', 'c', 'd'];
var $test = $('.test');
for (var i = 0; i < list.length; i++) {
  $test.eq(i).html(list[i]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
0

From what I understand, you'd like to populate your html so that you get

<div class="test">apple</div>
<div class="test">banana</div>
<div class="test">pear</div>
<div class="test">kiwi</div>

but instead you are getting

<div class="test">kiwi</div>
<div class="test">kiwi</div>
<div class="test">kiwi</div>
<div class="test">kiwi</div>

Is that correct?

If so, it's because

$('.test').html()

selects every matching instance. you aren't looping over the divs.

bfrizzell
  • 54
  • 1
  • 7
0

The issue is that this statement:

$('.test').html(produit[i].nom);

sets the HTML for ALL .test elements on every iteration of your loop, thus they are all set to the value of produit[i].nom on every iteration of your for loop so they all end up with the value at the last iteration of your loop. You aren't iterating over the .test elements to set them one at a time.


There are many different ways to do this, but I'll suggest an alternative approach that uses jQuery's .each() to iterate over your collection and then assigns the right HTML to each element:

var produit = [apple,banana,pear,kiwi];

$(".test").each(function(index, element) {
    $(element).html(produit[index].nom);
});

This is also a little more efficient that some other methods because it evaluates the selector $(".test") only once and then iterates that one list of elements rather than re-evaluate the selector every time through the loop.


jQuery has lots of tricks up its sleeve. It turns out that the .html() method can also take a callback function that will be called separately for each element in the collection. So, you can also do this:

var produit = [apple,banana,pear,kiwi];

$(".test").html(function(index) {
    return produit[index].nom;
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979